Swing/CheckBoxesInTableCell のバックアップの現在との差分(No.10)
TITLE:JTableのCellにJCheckBoxを複数配置する
Posted by aterai at 2011-02-28
JTableのCellにJCheckBoxを複数配置する
JTableのセル中にJCheckBoxを複数個配置します。-
category: swing
folder: CheckBoxesInTableCell
title: JTableのCellにJCheckBoxを複数配置する
tags: [JTable, JCheckBox, TableCellRenderer, TableCellEditor, JPanel, InputMap, ActionMap]
author: aterai
pubdate: 2011-02-28T15:07:56+09:00
description: JTableのセル中にJCheckBoxを複数個配置します。
image:
hreflang:
href: https://java-swing-tips.blogspot.com/2011/03/checkboxes-in-jtable-cell.html lang: en
概要
JTable
のセル中にJCheckBox
を複数個配置します。
- &jnlp;
- &jar;
- &zip;
Screenshot
Advertisement
サンプルコード
#spanend
#spanadd
* サンプルコード [#sourcecode]
#spanend
#spanadd
#code(link){{
#spanend
class CheckBoxesPanel extends JPanel {
private static final String OSNAME = System.getProperty("os.name");
protected final String[] title = {"r", "w", "x"};
public final JCheckBox[] buttons;
public JCheckBox[] buttons;
public CheckBoxesPanel() {
super();
setOpaque(false);
setBackground(new Color(0,0,0,0));
setBackground(new Color(0x0, true));
setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
initButtons();
}
#spanadd
#spanend
protected void initButtons() {
buttons = new JCheckBox[title.length];
for(int i=0; i<buttons.length; i++) {
for (int i = 0; i < buttons.length; i++) {
JCheckBox b = new JCheckBox(title[i]);
b.setOpaque(false);
b.setFocusable(false);
b.setRolloverEnabled(false);
b.setBackground(new Color(0,0,0,0));
b.setBackground(new Color(0x0, true));
buttons[i] = b;
add(b);
add(Box.createHorizontalStrut(5));
}
}
#spanadd
#spanend
protected void updateButtons(Object v) {
Integer i = (Integer)(v==null?0:v);
buttons[0].setSelected((i&(1<<2))!=0);
buttons[1].setSelected((i&(1<<1))!=0);
buttons[2].setSelected((i&(1<<0))!=0);
if ("Windows 7".equals(OSNAME)) { //Windows aero?
removeAll();
initButtons();
}
Integer i = (Integer) (v == null ? 0 : v);
buttons[0].setSelected((i & (1 << 2)) != 0);
buttons[1].setSelected((i & (1 << 1)) != 0);
buttons[2].setSelected((i & (1 << 0)) != 0);
}
}
#spandel
#spanend
class CheckBoxesRenderer extends CheckBoxesPanel
implements TableCellRenderer, Serializable {
public CheckBoxesRenderer() {
super();
setName("Table.cellRenderer");
}
#spanadd
#spanend
@Override public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus, int row, int column) {
updateButtons(value);
return this;
}
public static class UIResource extends CheckBoxesRenderer
implements UIResource{}
#spanadd
#spanend
public static class UIResource extends CheckBoxesRenderer implements UIResource {}
}
#spandel
#spanend
class CheckBoxesEditor extends CheckBoxesPanel
implements TableCellEditor, Serializable {
public CheckBoxesEditor() {
ActionListener al = new ActionListener() {
@Override public void actionPerformed(ActionEvent e) {
fireEditingStopped();
}
};
ActionMap am = getActionMap();
for(int i=0; i<buttons.length; i++) {
for (int i = 0; i < buttons.length; i++) {
final JCheckBox b = buttons[i];
b.addActionListener(al);
am.put(title[i], new AbstractAction(title[i]) {
public void actionPerformed(ActionEvent e) {
@Override public void actionPerformed(ActionEvent e) {
b.setSelected(!b.isSelected());
fireEditingStopped();
}
});
}
InputMap im = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_R, 0), title[0]);
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_W, 0), title[1]);
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_X, 0), title[2]);
}
#spanadd
#spanend
@Override public Component getTableCellEditorComponent(JTable table,
Object value, boolean isSelected, int row, int column) {
updateButtons(value);
return this;
}
#spanadd
#spanend
@Override public Object getCellEditorValue() {
int i = 0;
if(buttons[0].isSelected()) i|=1<<2;
if(buttons[1].isSelected()) i|=1<<1;
if(buttons[2].isSelected()) i|=1<<0;
if (buttons[0].isSelected()) i |= 1 << 2;
if (buttons[1].isSelected()) i |= 1 << 1;
if (buttons[2].isSelected()) i |= 1 << 0;
return i;
}
//Copid from AbstractCellEditor
// Copied from AbstractCellEditor
protected EventListenerList listenerList = new EventListenerList();
transient protected ChangeEvent changeEvent = null;
//......
// ...
解説
上記のサンプルでは、JTableのCell内に3つのJCheckBoxを配置したJPanelを作成し、これをCellRendererとCellEditorとして別々に使用しています。JCheckBoxをマウスでクリックすると、そのJCheckBoxの選択状態だけが変化します。解説
-
JTable
のセル内に3
つのJCheckBox
を配置したJPanel
を作成- この
JPanel
をCellRenderer
用とCellEditor
用として別々に使用
- この
-
JCheckBox
をマウスでクリックすると直下にあるJCheckBox
の選択状態のみ更新 - 編集中にカラムヘッダの移動やリサイズ(
JFrame
などのリサイズに連動)などが発生してもチェックした内容がリセットされないようにCellEditor
のチェックボックスがクリックされたらfireEditingStopped()
メソッドを呼び出して編集を終了し更新を確定する
- - ヘッダカラムの移動、リサイズ(JFrameなどのリサイズ)で、チェックした内容が消えてしまわないように、CellEditorのチェックボックスがクリックされたらfireEditingStopped()メソッドを呼び出して編集を終了し更新を確定するようにしています。
参考リンク
コメント
- ビットフラグを
EnumSet
に変更したサンプルをJTableの列にEnumSetを使用するに移動。 -- aterai -
rwx
セルを選択中にR、W、Xキーを入力すると、そのチェックが切り替わるようにInputMap
、ActionMap
を追加。 -- aterai -
Windows
環境でAero
効果を有効にしていると?、残像が表示される場合がある障害を修正。 -- aterai
参考リンク
コメント
- ビットフラグをEnumSetに変更するテスト -- aterai
#spanend #spandel import java.awt.*; #spanend #spandel import java.awt.event.*; #spanend #spandel import java.util.*; #spanend #spandel import javax.swing.*; #spanend #spandel import javax.swing.event.*; #spanend #spandel import javax.swing.table.*; #spanend #spandel public class EnumSetTest { #spanend String[] columnNames = { "user", "rwx" }; Object[][] data = { {"owner", EnumSet.of(Permissions.READ, Permissions.WRITE, Permissions.EXECUTE)}, {"group", EnumSet.of(Permissions.READ)}, {"other", EnumSet.noneOf(Permissions.class)} }; DefaultTableModel model = new DefaultTableModel(data, columnNames) { @Override public Class<?> getColumnClass(int column) { return getValueAt(0, column).getClass(); } }; JTable table = new JTable(model); public JComponent makeUI() { CheckBoxEditorRenderer cer = new CheckBoxEditorRenderer(); TableColumn c = table.getColumnModel().getColumn(1); c.setCellRenderer(cer); c.setCellEditor(cer); c.setPreferredWidth(180); #spandel #spanend final EnumMap<Permissions, Integer> map = new EnumMap<Permissions, Integer>(Permissions.class); map.put(Permissions.READ, 1<<2); map.put(Permissions.WRITE, 1<<1); map.put(Permissions.EXECUTE, 1<<0); #spandel #spanend JPanel p = new JPanel(new BorderLayout()); p.add(new JScrollPane(table)); p.add(new JButton(new AbstractAction("chmod") { @Override public void actionPerformed(ActionEvent e) { StringBuilder buf = new StringBuilder(9); String M = "-"; for (int i=0; i<model.getRowCount(); i++) { @SuppressWarnings("unchecked") EnumSet<Permissions> v = (EnumSet<Permissions>)model.getValueAt(i, 1); int flg = 0; if (v.contains(Permissions.READ)) { flg|=map.get(Permissions.READ); buf.append("r"); } else { buf.append(M); } if (v.contains(Permissions.WRITE)) { flg|=map.get(Permissions.WRITE); buf.append("w"); } else { buf.append(M); } if (v.contains(Permissions.EXECUTE)) { flg|=map.get(Permissions.EXECUTE); buf.append("x"); } else { buf.append(M); } System.out.print(flg); } System.out.println(" "+M+buf.toString()); } }), BorderLayout.SOUTH); return p; } public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { createAndShowGUI(); } }); } public static void createAndShowGUI() { JFrame f = new JFrame(); f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); f.getContentPane().add(new EnumSetTest().makeUI()); f.setSize(320,200); f.setLocationRelativeTo(null); f.setVisible(true); } #spandel } #spanend #spandel enum Permissions { EXECUTE, WRITE, READ; } #spanend #spandel class CheckBoxesPanel extends JPanel { #spanend protected final String[] title = {"r", "w", "x"}; public final JCheckBox[] buttons; public CheckBoxesPanel() { super(); setOpaque(false); setBackground(new Color(0,0,0,0)); setLayout(new BoxLayout(this, BoxLayout.X_AXIS)); buttons = new JCheckBox[title.length]; for (int i=0; i<buttons.length; i++) { JCheckBox b = new JCheckBox(title[i]); b.setOpaque(false); b.setFocusable(false); b.setRolloverEnabled(false); b.setBackground(new Color(0,0,0,0)); buttons[i] = b; add(b); add(Box.createHorizontalStrut(5)); } } protected void updateButtons(Object v) { @SuppressWarnings("unchecked") EnumSet<Permissions> f = (v==null)? EnumSet.noneOf(Permissions.class) :(EnumSet<Permissions>)v; buttons[0].setSelected(f.contains(Permissions.READ)); buttons[1].setSelected(f.contains(Permissions.WRITE)); buttons[2].setSelected(f.contains(Permissions.EXECUTE)); } #spandel // protected void updateButtons(Object v) { #spanend #spandel // Integer i = (Integer)(v==null?0:v); #spanend #spandel // buttons[0].setSelected((i&(1<<2))!=0); #spanend #spandel // buttons[1].setSelected((i&(1<<1))!=0); #spanend #spandel // buttons[2].setSelected((i&(1<<0))!=0); #spanend #spandel // } #spanend #spandel } #spanend #spandel #spanend #spandel class CheckBoxesRenderer extends CheckBoxesPanel implements TableCellRenderer { #spanend public CheckBoxesRenderer() { super(); setName("Table.cellRenderer"); } @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { updateButtons(value); return this; } #spandel } #spanend #spandel #spanend #spandel class CheckBoxesEditor extends CheckBoxesPanel implements TableCellEditor { #spanend public CheckBoxesEditor() { ActionListener al = new ActionListener() { @Override public void actionPerformed(ActionEvent e) { fireEditingStopped(); } }; } @Override public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { updateButtons(value); return this; } @Override public Object getCellEditorValue() { EnumSet<Permissions> f = EnumSet.noneOf(Permissions.class); if (buttons[0].isSelected()) f.add(Permissions.READ); if (buttons[1].isSelected()) f.add(Permissions.WRITE); if (buttons[2].isSelected()) f.add(Permissions.EXECUTE); return f; } #spandel // @Override public Object getCellEditorValue() { #spanend #spandel // int i = 0; #spanend #spandel // if (buttons[0].isSelected()) i|=1<<2; #spanend #spandel // if (buttons[1].isSelected()) i|=1<<1; #spanend #spandel // if (buttons[2].isSelected()) i|=1<<0; #spanend #spandel // return i; #spanend #spandel // } #spanend #spandel #spanend //Copid from AbstractCellEditor //protected EventListenerList listenerList = new EventListenerList(); transient protected ChangeEvent changeEvent = null; #spandel #spanend @Override public boolean isCellEditable(java.util.EventObject e) { return true; } @Override public boolean shouldSelectCell(java.util.EventObject anEvent) { return true; } @Override public boolean stopCellEditing() { fireEditingStopped(); return true; } @Override public void cancelCellEditing() { fireEditingCanceled(); } @Override public void addCellEditorListener(CellEditorListener l) { listenerList.add(CellEditorListener.class, l); } @Override public void removeCellEditorListener(CellEditorListener l) { listenerList.remove(CellEditorListener.class, l); } public CellEditorListener[] getCellEditorListeners() { return (CellEditorListener[])listenerList.getListeners(CellEditorListener.class); } protected void fireEditingStopped() { Object[] listeners = listenerList.getListenerList(); for (int i = listeners.length-2; i>=0; i-=2) { if (listeners[i]==CellEditorListener.class) { if (changeEvent == null) changeEvent = new ChangeEvent(this); ((CellEditorListener)listeners[i+1]).editingStopped(changeEvent); } } } protected void fireEditingCanceled() { Object[] listeners = listenerList.getListenerList(); for (int i = listeners.length-2; i>=0; i-=2) { if (listeners[i]==CellEditorListener.class) { if (changeEvent == null) changeEvent = new ChangeEvent(this); ((CellEditorListener)listeners[i+1]).editingCanceled(changeEvent); } } } #spandel } #spanend #spandel
- rwxセル選択中にキーボードからr,w,xを入力するとチェックが切り替わるようにInputMap, ActionMapを追加。 -- aterai