Recently I wanted to have a clickable button in a table. Searching on
Google for JButton in
JTable I found a
couple of suggestions, most notably this DevX
article and this
There was also a StackOverflow
that just referenced other solutions. None really satisfied me. So
borrowing their ideas I created my own solution.
Fundamentally, there are two problems with having a JButton in a JTable.
Firstly, by default a JTable will display cell values as a String, so
JButtons appear as “javax.swing.JButton”. Secondly, a JTable does not
pass clicks through to the cells.
To display the buttons correctly a custom cell renderer needs to be
applied to any columns displaying JButtons. This can be done with the
(this assumes that there is a column in the table labelled “Button1”.
The button renderer is below. The default renderer always returns a
JLabel, but this one returns a JButton after colouring it in an
appropriate manner. Note, this renderer assumes the contents of column
will always be a JButton and will throw an exception if this is not the
case. If the table column may not contain JButtons, just extend
DefaultTableCellRenderer, detect if the value is a JButton (or even a
Swing component) with instanceof, otherwise call super. This Sun
may help with this.
To get the table to pass clicks through to the button, add a mouse
listener to the table with
table.addMouseListener(new JTableButtonMouseListener(table)). This
mouse listener (example below) will have to take the click, work out in
which cell it occurred and if that cell contains a JButton, click it.
And with that, the buttons in your table should start to work. All you
need to do is return the buttons (which perform the required actions)
when requested from your model, using getValueAt(). A complete working
example is below.
Comments:I have removed the commenting system (for privacy concerns), below are the comments that were left on this post before doing so…
yonaides @ 2014-04-15 - Excelente ejemplo!
Lily @ 2014-07-08 - Do you have a function for the button to delete the entire row ? Instead of a messagebox?