Java Tips Weblog

Table Button Column

Posted by Rob Camick on July 12, 2009

A JTable is used to disply rows of data. There may be times when you want to do some processing on a row of data. Maybe you want to display a popup form with more details or maybe you simply want to delete a row. In these cases it may be desireable to add a button to one of the table columns so you can invoke this processing. The problem is that JTable doesn’t support a button renderer or editor.

After playing around a bit, the best solution I could come up with was to create a class that is both a renderer and an editor. The result is the ButtonColumn class. When you create the class you specify an Action that is to be invoked when the button is pressed. You also specify the column that is used to contain the button so that the renderer and editor can be automatically installed on the appropriate TableColumn of the TableColumnModel.

A table using a ButtonColumn as a renderer would look like this:

Table-Button-Column

The button can be invoked by using the mouse or the keyboard. Using the Metal or Windows LAF you would use the space bar to invoke the button (I’m not sure about other LAF’s). You can also set a mnemonic to invoke the button. You can set the mnemonic using the setMnemonic() method. In the example above I used KeyEvent.VK_D as the mnemonic.

Notice how the border on the first button is a different color? This indicates that the button has focus and can be invoked by using the keyboard as mentioned above. I decided to use this approach since I couldn’t figure out how to invoke the normal “focus painted” code on a rendered button. You can change the Border using the setFocusBorder() method.

The key to the ButtonColumn class is the usage of an Action to perform the custom processing. When the button is clicked an ActionEvent is created and the actionPerformed() method of the Action is invoked. The table will be the source of the event. Also, the action command will contain the “model” row number of the clicked button. The reason for passing a row number is that multiple rows could be selected so you can’t depend on the table.getSelectedRow() method to return the appropriate row number. The reason for passing the model row is so you can access the TableModel using the same index whether the table uses a RowSorter or not.

The code to delete a row from a table using the DefaultTableModel would be:

Action delete = new AbstractAction()
{
    public void actionPerformed(ActionEvent e)
    {
        JTable table = (JTable)e.getSource();
        int modelRow = Integer.valueOf( e.getActionCommand() );
        ((DefaultTableModel)table.getModel()).removeRow(modelRow);
    }
};

ButtonColumn buttonColumn = new ButtonColumn(table, delete, 2);
buttonColumn.setMnemonic(KeyEvent.VK_D);

Of course you would probably want to add a confirm dialog before actually deleting the row. Anyway, hopefully you will find the ButtonColumn class easy to use.
 

Get The Code

ButtonColumn.java

Related Reading

Java Tutorials: Concepts – Editors and Renderers

7 Responses to “Table Button Column”

  1. sarcan said

    Hi Rob,

    always a pleasure reading your blog. There seems to be a glitch with this particular example, though. The actionCommand property generated by ButtonColumn contains the ‘view row’, not the ‘model row’. If you install a RowSorter on your table and change the row order you’ll end up deleting the wrong one, so the line in actionPerformed should probably read

    int row = table.convertRowIndexToModel(Integer.valueOf( e.getActionCommand()));

    best regards,
    sarcan

  2. Eitan said

    Hi Rob,

    Like Sarcan said “it is a pleasure”.

    If I am not mistaken you do not need
    the

    public void mouseMoved(MouseEvent e) {}

    • Rob Camick said

      Boy, I was sleeping while doing this one. Thanks, the line has been removed.

      Its nice to know people actually take the time to read and understand the code.

  3. André Uhres said

    Well done. Just one minor point: you use the terms “TableButton”, “TableColumn” and “ButtonColumn” to refer to the same class, which is a little bit confusing at first reading. I suppose you changed the class name and forgot to update the text.

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <pre> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>