简体   繁体   中英

Repaint Table issue with Swing JTable

I am working with swing JTable and have a trouble with repainting table. I draw a JTable with thr following code

Object[] column = new Object[]{"Entity", "Attribute"};
Object[][] rowData = new Object[][]{{"E1", "A1"},{"E2", "A2"}};
TableCellRenderer cellRenderer = new TableCellRenderer();

JTable table = new JTable(new DefaultTableModel(rowData, column));

table.setCellSelectionEnabled(true);

table.getColumnModel().getColumn(0).setCellRenderer(cellRenderer);

Below is my table renderer code ..

public class TableCellRenderer implements javax.swing.table.TableCellRenderer {

//private JPanel panel;
JTextField field;
private JTable table;   

@Override
public Component getTableCellRendererComponent(final JTable table, final Object value,
        boolean isSelected, boolean hasFocus, final int row, final int column) {

    this.table = table;
    //JTextField field = null;
    System.out.println("Rendere : Row : " + row + "Column : " + column);
    final JPanel panel = new JPanel();
    panel.setLayout(new BorderLayout());

    JButton button = new JButton("?");
    button.setPreferredSize(new Dimension(20, panel.getHeight()));
    button.addActionListener(new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent arg0) {
            new SelectionDialog(panel, table, value, row, column);

        }
    });
    if(table.getValueAt(row, column) != null){
        field = new JTextField(table.getValueAt(row, column).toString());
    }else{
        field = new JTextField(table.getValueAt(row, column).toString());
    }
    field.setPreferredSize(new Dimension(30, panel.getHeight()));
    panel.add(field, BorderLayout.WEST);
    panel.add(button, BorderLayout.EAST);

    return panel;

}

this is how i am updating contents of a cell in table..

SelectionDialog.this.table.getModel().setValueAt("E7", 0, 0);

I am updating the table model data via the SelectionDialog for eg change data at row 0, colum 0 to E7 etc. After changing data in table model i have tried the following options but none of them has refreshed the table data in view however the data in model of JTable was updated correctly. If I add a new row on the fly and then call the below methods then every thing work fine but if I modify data in the model of an existing row then none of the solution mentioned below is working

//((DefaultTableModel)SelectionDialog.this.table.getModel()).addRow(new Object[]{"E3", "A3"});
            //((DefaultTableModel)SelectionDialog.this.table.getModel()).fireTableCellUpdated(SelectionDialog.this.row, SelectionDialog.this.column);
            //((DefaultTableModel)SelectionDialog.this.table.getModel()).fireTableChanged(new TableModelEvent(SelectionDialog.this.table.getModel()));
            //((DefaultTableModel)SelectionDialog.this.table.getModel()).fireTableStructureChanged();
            //SelectionDialog.this.table.repaint();
        //  SelectionDialog.this.table.revalidate();

Please provide any insights about the problem as I am to swing and may have missed some very prominent things.

Edit 1: Just adding one more note which i wanted to place earlier but don't know how i missed. Table is not updated in general but if i focus out from the cell in which change was made or i change the size of table then it immediately change the contents of that particular cell to fresh selected value.

Problem Solved:

I am placing my findings for someone who is facing similar problem.

I rendered a button and a text box inside each cell in my table. When button was clicked (Editor code is not provided as it looks irrelevant to me to place here) a dialog appear which inputs value from user and update the specific column and row. The lines i mentioned as not working at the end of my post (before edit 1) were working correctly however renderer was not executing unless i manually focus out from the selected cell (whose button was clicked) or manually change the size of jtable which make sense as button was inside editor and button click shows that cell is edited and off-course renderer will not execute unless editing is finished which requires focus out or enter key etc. I applied the following code as

table.editCellAt(-1, -1);

It focus out from the edited cell (edited with the button) and hence renderer executes and work as expected.

When you are using a DefaultTableModel and you want to update a certain value, you need to use the DefaultTableModel#setValueAt method.

Calling this method (on the Event Dispatch Thread of course) will update your model and fire the necessary events. Those events will cause your JTable to update itself.

A few additional remarks about your renderer:

  • Creating new components in each call of your renderer is not the way to go. This becomes incredibly slow for large tables. Create all components once in the constructor of your renderer, and just update their state
  • Adding a JButton to your table in the renderer has no effect, unless you have an editor as well. The button will not be clickable, and the action listener you attach to it will never be called. See the renderers and editors section in the JTable tutorial for more information.
  • There should be no need to call getValueAt in your renderer. The value is passed in as one of the arguments

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM