JButton inside JTable Cell
Hi guys, I really need some help......
I am working with JTable, and would like to show a JButton inside the last table column... This button will perform some actions when the user click on it.
But I don't know how to solve some problems. I already create the table model, renderer, cell editor, my fired event are almos right, but I really think that are a lot to do until finish it.
Right now, I am with the followign problems:
1) How can I do to the button (inside the table) fire an event every time the user click on it, instead to force the user to click on button and press the enter?!!?!?
2) I would like to made the button disappear after the user click on it (or force it do setEnabled(false) to prevent user repeat the same action. To solve it I set the CellEditor component to not visible when the stoppingEdit is finished, but whem the user click on another table row my old button becomes visible automaticaly. How can I fix this things?!!?
ps: I know that it is a very complicated thing, and propably will need a lot of source code, so if anyone knows a good tutorial it will be welcome too.
Thanks all
> But some times neither all rows are removed
Use DefaultTableModel.setRowCount(0);
> 2) I would like to made the button disappear after the user click on it (or
> force it do setEnabled(false) to prevent user repeat the same action.
From my example below you could set the value of the cell to "". Then you could override the isCellEditable() method to return false when the "button cell" contains "".
Here is some example code I've been playing with that may (or may not) give you some ideas:
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.table.*;
public class TableButton3 extends JFrame
{
public TableButton3()
{
String[] columnNames = {"Date", "String", "Integer", "Decimal", ""};
Object[][] data =
{
{new Date(), "A", new Integer(1), new Double(5.1), "Delete0"},
{new Date(), "B", new Integer(2), new Double(6.2), "Delete1"},
{new Date(), "C", new Integer(3), new Double(7.3), "Delete2"},
{new Date(), "D", new Integer(4), new Double(8.4), "Delete3"}
};
DefaultTableModel model = new DefaultTableModel(data, columnNames);
JTable table = new JTable( model )
{
// Returning the Class of each column will allow different
// renderers to be used based on Class
public Class getColumnClass(int column)
{
return getValueAt(0, column).getClass();
}
};
JScrollPane scrollPane = new JScrollPane( table );
getContentPane().add( scrollPane );
// Create button column
ButtonColumn buttonColumn = new ButtonColumn(table, 4);
}
public static void main(String[] args)
{
TableButton3 frame = new TableButton3();
frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
frame.pack();
frame.setVisible(true);
}
class ButtonColumn extends AbstractCellEditor
implements TableCellRenderer, TableCellEditor, ActionListener
{
JTable table;
JButton renderButton;
JButton editButton;
String text;
public ButtonColumn(JTable table, int column)
{
super();
this.table = table;
renderButton = new JButton();
editButton = new JButton();
editButton.setFocusPainted( false );
editButton.addActionListener( this );
TableColumnModel columnModel = table.getColumnModel();
columnModel.getColumn(column).setCellRenderer( this );
columnModel.getColumn(column).setCellEditor( this );
}
public Component getTableCellRendererComponent(
JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
{
if (hasFocus)
{
renderButton.setForeground(table.getForeground());
renderButton.setBackground(UIManager.getColor("Button.background"));
}
else if (isSelected)
{
renderButton.setForeground(table.getSelectionForeground());
renderButton.setBackground(table.getSelectionBackground());
}
else
{
renderButton.setForeground(table.getForeground());
renderButton.setBackground(UIManager.getColor("Button.background"));
}
renderButton.setText( (value == null) ? "" : value.toString() );
return renderButton;
}
public Component getTableCellEditorComponent(
JTable table, Object value, boolean isSelected, int row, int column)
{
text = (value == null) ? "" : value.toString();
editButton.setText( text );
return editButton;
}
public Object getCellEditorValue()
{
return text;
}
public void actionPerformed(ActionEvent e)
{
fireEditingStopped();
System.out.println( e.getActionCommand() + " : " + table.getSelectedRow());
}
}
}
hi camickr,
First of all thanks! Your code helps me a lot! :) Clear and fast, as I love its!
Do know that it's an old topic, but I've got a simple question. I'm not a swing expert, so hope this question would not sound stupid...
I pay attention to your code, and here is what I've concluded: (do know that it was a simple example)
you are using two components, since the TableCellRenderer and TableCellEditor are implemented in the same class: an editButton and a renderButton (for each method)
If we're digging into a set of components, such as a JPanel in a cell that contains a lot of labels, buttons and so on, does it mean that we must have, actually, two instances of each component? (one by interface, since our class implements each of it)
If my preceding assertion is true, what do you think of this?
columnModel.getColumn(column).setCellRenderer( this );
columnModel.getColumn(column).setCellEditor( this );
// maybe this could do the trick (of course outside the ButtonColumn class
columnModel.getColumn(column).setCellRenderer( new ButtonColumn());
columnModel.getColumn(column).setCellEditor( new ButtonColumn() );
Have a good day!
Mathieu.