3

Up till now I had a definition of the JTable like this:

    JTable table = new JTable(model) {
        @Override
        public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
            Component c = super.prepareRenderer(renderer, row, column);
            TradeTableModel model = (TradeTableModel) getModel();
            if ((Boolean) model.getValueAt(row, model.findColumn("Select"))) {
                Side s = (Side) model.getValueAt(row, model.findColumn("Side"));
                if (s == Side.BUY)
                    c.setBackground(Color.BLUE);
                else
                    c.setBackground(Color.red);
            }
            else {
                c.setBackground(Color.white);
            }
            return c;
        }
    };

This was to make sure the rows will change color based on selecting the boolean column value. At my AbstractTableModel I specified set value method as follows:

public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
    assert columnIndex == 5;

    try{
        Selectable t = trades.get(rowIndex);
        t.setSelected((Boolean)aValue);
        fireTableDataChanged();
        //fireTableCellUpdated(rowIndex, columnIndex);
    }
    catch(Exception  e){
        throw new IllegalArgumentException("Object to set was not subtype of boolean");
    }

}

If I use fireTableDataChanged() the color is updated as I click the checkbox on the gui. Howver, I really want to send the fireTableCellUpdated(rowIndex, columnIndex) as other handlers need to know the location of the cell. However, in this scenario, the row only changes if I click on other row in the table, as if it was delayed and waited for some other event to happen.

ANy ideas why that is the case?

mKorbel
  • 109,525
  • 20
  • 134
  • 319
Bober02
  • 15,034
  • 31
  • 92
  • 178
  • the fireXX needs to include all model values that might be affected by setValueAt(..). Depending on the exact context, it should fire a slightly more broad event: f.i. if some condition somewhere else in the row is affect, fire a tableRowUpdate. Or if some other rows might be affected, fire a tableRowsUpdated(0, getRowCount()) – kleopatra Aug 02 '12 at 21:12
  • IF you want to use fireTableCellUpdated, I would suggest you need to fire two events. I the first is to notify that the OLD selected cell has changed and the second is to notify that the NEW selected cell has changed. The important thing to remember here is that the JTable's paint process is highly optimised, so calling cellUpdated will generally only update that cell and won't effect any other cells – MadProgrammer Aug 02 '12 at 21:42
  • I decided to fire two events: one for the row, to change its paint, then cell updated event to do further processing on that particular cell – Bober02 Aug 03 '12 at 07:19

2 Answers2

2
  • have to notify proper method, fireTableCellUpdated(row, col);

  • more about AbstractTableModel and prepareRenderer and its methods, please read comment by @camickr

  • have look at convertXxxToModel in the case that JTable is filtered or sorted, e.i.

Community
  • 1
  • 1
mKorbel
  • 109,525
  • 20
  • 134
  • 319
  • So I need to simply repaint and revalidate the table to make the perpareRenderer to be invoked? – Bober02 Aug 02 '12 at 16:30
  • not this job is done by defaul by `prepareRenderer`, are you tried to `redirect / change` value for `prepareRenderer` from `Boolean value` to another `column`, and I'd to suggest wrapp Coloring or formating into `if (table.getRows > 0)` to protect against `XxxException`... – mKorbel Aug 02 '12 at 16:46
2

Your (unseen) TableModel should fireTableXxxXxxx() as required in order to notify all listeners. DefaultTableModel does this automatically; AbstractTableModel should do so in setValueAt(). One such listener is the table itself. If "other handlers need to know the location of the cell," they can register for TableModelEvent instances via addTableModelListener(). They can also listen for User Selections as needed.

trashgod
  • 203,806
  • 29
  • 246
  • 1,045