Table Cell Listener
Posted by Rob Camick on June 7, 2009
A TableModelListener is used to listen for changes to a TableModel. Relying solely on the TableModelListener can have potential drawbacks. In particular:
- in some cases, a TableModelEvent is fired even though nothing has changed. This would happen when you place a table cell in editing mode but then simply tab (or click) off the cell without changing anything.
- in all cases, when the event is received you only have access to the current state of the TableModel. This means that you know what has changed, but you don’t know what it was changed from.
In the first case this may result in extra processing being repeated, which may or may not be a big deal depending on the type of processing required. The second case is obviously a bigger problem when you have processing that needs to know the previous value of the cell. The information simply isn’t available.
There is a simple solution to handle both concerns. However, the solution discussed here is only applicable to updates made to the TableModel through a JTable via a table cell editor. The solution identifies when an actual change in the cell data occurs and then it invokes custom processing. The TableCellListener class implements the solution.
Lets take a quick look at how the TableCellListener works. A JTable fires a PropertyChangeEvent when a cell:
- starts editing – therefore we can save the current value of the cell before it is changed (the old value)
- finishes editing – therefore we can retrieve the current value of the cell (the new value). In addition, we can now compare the old and new values and invoke processing when they are different.
When creating a TableCellListener you need to provide a JTable and an Action as the parameters. The table is specified so we can listen for the above PropertyChangeEvents. The Action will be invoked when the values have changed. The TableCellListener will be the source of the Action so you will be able to access all the information about the changed cell value.
Test the TableCellListener by adding it to any table using code like the following:
Action action = new AbstractAction()
{
public void actionPerformed(ActionEvent e)
{
TableCellListener tcl = (TableCellListener)e.getSource();
System.out.println("Row : " + tcl.getRow());
System.out.println("Column: " + tcl.getColumn());
System.out.println("Old : " + tcl.getOldValue());
System.out.println("New : " + tcl.getNewValue());
}
};
TableCellListener tcl = new TableCellListener(table, action);
In summary, the TableCellListener class can be used as a replacement for a TableModelListener in the special cases described above. Instead of implementing a TableModelListener you would implement an Action.
LD said
Hey Rob,
I implemented your TableCellListener class into my application and it works well. But I was wondering if it is possible to use the TableCellListener class to bring what I want to do to a higher level.
The thing is, I wanted to restrict the users only to enter positive values in the table cells, so I looked around in your blog and found this class. Now, after implementing the TableCellListener class, what my application does, concerning the tables, is: when the user edits a cell, and he enters a negative value, then hits tab or enter, the cell goes back to its old value.
However, what I would really want is: instead of letting the user enter all the unwanted characters (-~!@#$% etc…), the application should consume all of that – meaning not letting the user enter those character at all in the first place.
Can we do that using your TableCellListener class, or would recommend something else?
Regards,
LD
Rob Camick said
Editing data is not part of the functionality of the TableCellListener. To do that you need to create a custom cell editor. The Swing tutorial explains the concept. You can use a JFormattedTextField as the editor or a JTextField with a DocumentFilter.