Java Tips Weblog

  • Blog Stats

    • 818,316 hits
  • Categories

  • Archives

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.

Get The Code

TableCellListener.java

About these ads

34 Responses to “Table Cell Listener”

  1. 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.

  2. Chintan said

    Rob,
    I liked the TableCellListener example that you have put up. But my environment is Java 1.5 so in effect I cannot use the utility since “convertRowIndexToModel” is not available in 1.5. Is there any workaround?

    Thanks for all the help.

    ~ Chintan

    • Rob Camick said

      Well, it means you aren’t using any of the sorting or filtering features that where added in JDK6, so you should be able to just use the editing row directly.

      • Chintan said

        .Yeah, I figured that out & did this.

        // row = table.convertRowIndexToModel(table.getEditingRow());
        row = table.getEditingRow();

        Thanks for the prompt response. If you had be kind enough to let me know if it is possible to disable the table cell listener for certain columns then that would be great. I tried this,

        if (“tableCellEditor”.equals(e.getPropertyName())) {
        if (table.getEditingColumn() != columnIndexToBeIgnored) {
        if (table.isEditing()) {


        But this doesnt seem to work. Also there is amoment at which the table.editifingColumn becomes -1 even though I am in a specific column.

        Thanks again.

        • Rob Camick said

          The comment in processEditingStarted() explains why you have this problem with the column.

          The TableCellListener was designed to replace the TableModelListener, so this means the event is always fired. So your custom Action should filter out the columns you want to ignore.

  3. Manish said

    Hi,
    I am working on table model with combobox in jtable (in column 2).
    How can i get the selected item for the selected combobox?

    Thanks in advance.

  4. Mike B. said

    Wow this is really helpful.
    But I was wondering how can I not include the cells in the first column of my table?

    • Rob Camick said

      The event is fired for all rows/columns. If you don’t care about the first column then you just ignore it. At the beginning of your Action you just add something like:

      if (tcl.getColumn() == 0) return;

  5. alvaro said

    excelent code it was really helpfull and simple to use

  6. Jet said

    you’re a life saver man… thank you!

  7. Anonymous said

    Very good !!!

  8. Jeff said

    THANK YOU ! I know this is a couple years old now but I’ve spent 3 days trying to implement this functionality using listselections and listeners and whatnot with only partial success.

    I just had to change …
    Action action = new AbstractAction()
    to …
    AbstractAction action = new AbstractAction()

    (using netbeans)

    But it worked like a charm! Should be part of core!

  9. Anonymous said

    Not sure why it doesn’t work for you when using Netbeans. AbstractAction implements the Action interface so you should be able to use the code as given in the example above. Anyway, glad the class does what you need.

    Not sure why this comment is displayed with “Anonymous” as the user. Something is wrong with the comments.

  10. d3viam said

    In:

    public TableCellListener(JTable table, Action action)
    	{
    		this.table = table;
    		this.action = action;
    		this.table.addPropertyChangeListener( this );
    	}
    

    Line: this.table.addPropertyChangeListener( this );
    Netbeans comment: Leaking this in constructor

  11. Amit said

    Excellent !

    Just what I wanted :)

    Thank you!!

  12. Mubashir said

    This requires pressing enter key, what i require is that when the value is changed the event automatically fires.

    • Rob Camick said

      This class has nothing to do with that type of functionality. If you want to know when data is changed in the editor then you need to add a DocumentListener to the editor.

      • Mubashir said

        Can you tell me how can i use The TableCellListener class with document listener event for the jtable. As I have written many events in my code for Action Event which uses your TableCellListener classs.

        • Mubashir said

          Thanks For Your Reply , Actually i expicitly called Table Click Event On My Save Button Click Event

          MouseEvent me = new MouseEvent(tblDetailInfo, 0, 0, 0, 100, 100, 1, false);
          for(MouseListener ml: tblDetailInfo.getMouseListeners()){
          ml.mouseClicked(me);
          }
          which solves my problem.

  13. Kasun Bandara said

    Nice work budy.
    How can i fire event even data hasn’t changed in cell ?

  14. Anonymous said

    Excellent code example for cell data change listener
    Thanks

  15. Anonymous said

    Works great! Thanks

  16. Excellent!
    It works like magic.

  17. to prevent null pointer exceptions i had to do this:

    ...
    // Determine if data was changed
    boolean data_changed = false;
    if ( newValue == null ) {
    	data_changed = ( oldValue != null );
    }
    else if ( oldValue == null ) {
    	data_changed = ( newValue != null );
    }
    else {
    	data_changed = !newValue.equals( oldValue ); 
    }
    
    // The data has changed, invoke the supplied Action
    if ( data_changed ) {
    ...
    
    • Rob Camick said

      Not sure why you needed to do that. The supplied code works fine for me. That is I don’t get an Exception in the TableCellListener class when changing a cell that contains a null or when setting a cell to a null value. This is the behaviour I was going for.

      Yes, the code in the sample Action does result in an Exception being thrown. The code in the Action is not complete as it should check for nulls. An Exception is still thrown in the Action with your fix as well.

  18. Sudheer said

    Excellent work Rob!!
    I have used this TableCellListener in my project. My table has three rows – first two rows has combobox, and third row has text field.
    And I am creating the two comboboxes dynamically with items when i am creating the rows.

    Now my problem is, when i change the value in first column combobox, the items in second column combobox should be changed accordingly.

    How to achieve this. I am struck here. because i have to get the row of the first combobox changed and update corresponding row second combobox.

    Could you please help me in this regard.

    Thanks!! in advance.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

 
Follow

Get every new post delivered to your Inbox.

Join 66 other followers

%d bloggers like this: