JTableのセルに複数のJButtonを配置する
Total: 21638, Today: 1, Yesterday: 5
Posted by aterai at
Last-modified:
Summary
JTableのセル内にクリック可能な複数のJButtonを配置します。
Screenshot

Advertisement
Source Code Examples
class ButtonsPanel extends JPanel {
public final List<JButton> buttons =
Arrays.asList(new JButton("view"), new JButton("edit"));
public ButtonsPanel() {
super();
setOpaque(true);
for (JButton b: buttons) {
b.setFocusable(false);
b.setRolloverEnabled(false);
add(b);
}
}
}
class ButtonsRenderer extends ButtonsPanel
implements TableCellRenderer {
public ButtonsRenderer() {
super();
setName("Table.cellRenderer");
}
@Override public Component getTableCellRendererComponent(
JTable table, Object value, boolean isSelected,
boolean hasFocus, int row, int column) {
Color bgc = isSelected ? table.getSelectionBackground()
: table.getBackground()
setBackground(bgc);
return this;
}
}
class ButtonsEditor extends ButtonsPanel
implements TableCellEditor {
public ButtonsEditor(final JTable table) {
super();
// ---->
// DEBUG: view button click
// -> control key down + edit button(same cell) press
// -> remain selection color
MouseListener ml = new MouseAdapter() {
@Override public void mousePressed(MouseEvent e) {
ButtonModel m = ((JButton) e.getSource()).getModel();
if (m.isPressed() && table.isRowSelected(table.getEditingRow())
&& e.isControlDown()) {
setBackground(table.getBackground());
}
}
};
buttons.get(0).addMouseListener(ml);
buttons.get(1).addMouseListener(ml);
// <----
buttons.get(0).addActionListener(new ActionListener() {
@Override public void actionPerformed(ActionEvent e) {
fireEditingStopped();
JOptionPane.showMessageDialog(table, "Viewing");
}
});
buttons.get(1).addActionListener(new ActionListener() {
@Override public void actionPerformed(ActionEvent e) {
int row = table.convertRowIndexToModel(table.getEditingRow());
Object o = table.getModel().getValueAt(row, 0);
fireEditingStopped();
JOptionPane.showMessageDialog(table, "Editing: " + o);
}
});
addMouseListener(new MouseAdapter() {
@Override public void mousePressed(MouseEvent e) {
fireEditingStopped();
}
});
}
@Override public Component getTableCellEditorComponent(JTable table,
Object value, boolean isSelected, int row, int column) {
this.setBackground(table.getSelectionBackground());
return this;
}
@Override public Object getCellEditorValue() {
return "";
}
// Copied from AbstractCellEditor
// protected EventListenerList listenerList = new EventListenerList();
transient protected ChangeEvent changeEvent = null;
@Override public boolean isCellEditable(java.util.EventObject e) {
return true;
}
// ...
View in GitHub: Java, KotlinDescription
上記のサンプルでは、CellRenderer用とCellEditor用にJButtonを2つ配置したJPanelをそれぞれ作成しています。CellRenderer用のJButtonは表示のみに使用するため、クリック後に実行するActionはCellEditor用のJButtonだけに設定しています。
LookAndFeelなどが更新されたらJTable#updateUI()メソッド内でSwingUtilities#updateRendererOrEditorUI()メソッドを呼び出すなどして各セルレンダラーやセルエディタ(これらはJTableの子コンポーネントではないので)を更新AbstractCellEditorを継承するセルエディタはComponentもDefaultCellEditorも継承していないのでLookAndFeelを変更しても追従しない- そのため
JTable#updateUI()をオーバーライドしてセルエディタ自体を再作成するなどの対応が必要
- このサンプルでは、
Componentを継承(TableCellEditorを実装)するセルエディタを作成し、AbstractCellEditorから必要なメソッドをコピーして回避している
// SwingUtilities#updateRendererOrEditorUI()
static void updateRendererOrEditorUI(Object rendererOrEditor) {
if (rendererOrEditor == null) {
return;
}
Component component = null;
if (rendererOrEditor instanceof Component) {
component = (Component) rendererOrEditor;
}
if (rendererOrEditor instanceof DefaultCellEditor) {
component = ((DefaultCellEditor) rendererOrEditor).getComponent();
}
if (component != null) {
SwingUtilities.updateComponentTreeUI(component);
}
}
JSpinner(2つのJButtonとJTextFieldの組み合わせ)をCellEditorに使用する
Reference
- JTableのセルにJButtonを追加して行削除
- JTableのセルにHyperlinkを表示
- Table Button Column « Java Tips Weblog
- JTableのセル中にJRadioButtonを配置
- JTableのCellにJCheckBoxを複数配置する
- [JDK-8138667] java.lang.IllegalAccessError: tried to access method (for a protected method) - Java Bug System
Java 8でEventQueue.invokeLater( () -> fireEditingStopped() );ではなくEventQueue.invokeLater(ButtonsEditor.this::fireEditingStopped);のようなコードを実行するとIllegalAccessErrorになる場合があるJava 9で修正済