2

I have a JTable with few columns that are painted as checkboxes. What I want to do is to enable/disable checkbox from Column A by checking/unchecking corresponding checkbox in Column B.

I have managed to do it basing on this example, but I have a problem with newly enabled/disabled checkboxes - they are not refreshing properly. Checkbox which was enabled/disabled last is refreshed only after I click on any other cell in the table.

Problem looks like this ("Ref. structure" column is the one with enabled/disabled checkboxes):

Checkbox not enabled:

Checkbox not enabled

Checkbox not disabled:

Checkbox not disabled

This is my JTable code:

public class StructuresJTable extends JTable {

public StructuresJTable() {
    super();
}

public StructuresJTable(TableModel dm) {
    super(dm);
}

@Override
public Component prepareRenderer(TableCellRenderer renderer, int row,
        int col) {
    Component c = super.prepareRenderer(renderer, row, col);
    if (col == StructuresTableModel.COMPARISON_REF_STRUCT_COL) {
        c.setEnabled((Boolean) this.dataModel.getValueAt(row,
                StructuresTableModel.COMPARE_COL));
    } else {
        c.setEnabled(true);
    }
    return c;
}

}

Do you have any suggestions how to make it work?

Community
  • 1
  • 1
lasjak
  • 65
  • 2
  • 6

2 Answers2

3

Update: Using prepareRenderer() versus implementing TableCellRenderer isn't so important as conditioning the model correctly. If the model is correct, the view will follow. You'll need a suitable model, renderer and editor.

  • Model: You'll need some data structure to hold the state of each cell. In your implementation of TableModel, override setValueAt() to condition the desired state of each cell in the model as changes occur.

  • Renderer: In your TableCellRenderer, override getTableCellRendererComponent() to condition the renderer for each cell as specified in the model.

  • Editor: The DefaultCellEditor, used here implicitly, should be sufficient.

Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • [am I wrong or don't undestand](http://stackoverflow.com/questions/7045851/jtable-how-prepareeditor-works) +1 – mKorbel Jun 29 '12 at 07:03
  • @mKorbel: You are correct; the view should reflect the updated model automatically. – trashgod Jun 29 '12 at 10:01
  • @mKorbel your example repaints the whole table and I didn't want to have field with JTable in my TableModelListener. It works, but I found calling fireTableRowsUpdated(row, row) in TableModel setValue() method more preferable. – lasjak Jun 29 '12 at 10:29
  • 1
    @lasjak: Yes, your implementation of `TableModel` must notify it's listening `JTable` view; a row is the smallest reasonable update. – trashgod Jun 29 '12 at 10:34
  • @lasjak whaaaaaat, please .... this is about methods implemented in the JTable API not about prepareXxx, `1)` then don't use prepareXxx and to create an mostrum, sure two steps back, `2)` take my comment here as private discusion, – mKorbel Jun 29 '12 at 10:45
2

I haven't looked at your code, but in general with Swing tables, lists and trees, the renderer instance is reused to draw many rows. You need to tell the JTable that its contents has changed, so that it may redraw the relevant rows. Use the model to notify its TableModelListeners that some rows have changed.

sjr
  • 9,769
  • 1
  • 25
  • 36
  • I think that not true, JTable doesn't required repaint(), please see my comment in (@trashgod) post – mKorbel Jun 29 '12 at 07:04
  • Thank you, calling fireTableRowsUpdated(row, row); in my TableModel setValue() method worked. – lasjak Jun 29 '12 at 10:20
  • 2
    -1 for suggesting repaint() -- that's _never_ needed if the model is correctly implemented – kleopatra Jun 29 '12 at 10:47
  • [with important notice about TableModelListener](http://stackoverflow.com/questions/8099098/why-never-change-the-notifier-in-receiving-a-change-event) – mKorbel Jun 29 '12 at 11:05
  • @kleopatra: You are of course correct, I'll remove the suggestion :) – sjr Jun 29 '12 at 22:51