Swing/MultipleButtonsInTableCell のバックアップ差分(No.17)
- バックアップ一覧
- 現在との差分 を表示
- 現在との差分 - Visual を表示
- ソース を表示
- バックアップ を表示
- Swing/MultipleButtonsInTableCell へ行く。
- 1 (2009-10-06 (火) 11:55:06)
- 2 (2009-10-19 (月) 19:26:55)
- 3 (2009-11-03 (火) 04:36:55)
- 4 (2009-11-03 (火) 05:57:35)
- 5 (2011-03-04 (金) 15:57:52)
- 6 (2011-03-05 (土) 01:15:35)
- 7 (2011-03-10 (木) 02:33:21)
- 8 (2011-03-11 (金) 00:37:21)
- 9 (2011-05-06 (金) 18:49:11)
- 10 (2012-02-07 (火) 18:09:44)
- 11 (2012-09-28 (金) 19:36:52)
- 12 (2013-01-05 (土) 19:50:02)
- 13 (2013-05-24 (金) 11:57:26)
- 14 (2013-05-24 (金) 23:59:16)
- 15 (2013-07-21 (日) 02:37:44)
- 16 (2013-07-26 (金) 01:15:37)
- 17 (2013-08-17 (土) 01:12:15)
- 18 (2013-08-17 (土) 02:15:47)
- 19 (2014-05-15 (木) 18:18:57)
- 20 (2014-06-26 (木) 16:20:28)
- 21 (2014-11-07 (金) 03:09:24)
- 22 (2014-11-17 (月) 00:00:10)
- 23 (2014-11-21 (金) 18:29:32)
- 24 (2015-12-27 (日) 23:09:36)
- 25 (2017-06-15 (木) 15:23:24)
- 26 (2017-11-02 (木) 15:32:16)
- 27 (2018-02-24 (土) 19:51:30)
- 28 (2018-06-13 (水) 18:44:19)
- 29 (2020-06-07 (日) 15:57:34)
- 30 (2021-11-21 (日) 22:03:09)
- 31 (2023-05-20 (土) 01:55:25)
- 追加された行はこの色です。
- 削除された行はこの色です。
TITLE:JTableのセルに複数のJButtonを配置する #navi(../) #tags(JTable, TableCellEditor, TableCellRenderer, JButton, JPanel, ActionListener) RIGHT:Posted by &author(aterai); at 2009-10-05 *JTableのセルに複数のJButtonを配置する [#wd1c2d32] ``JTable``のセル内にクリック可能な複数の``JButton``を配置します。 -&jnlp; -&jar; -&zip; //#screenshot #ref(http://lh4.ggpht.com/_9Z4BYR88imo/TQTQRygoYeI/AAAAAAAAAfU/-Sr9o7PsQkM/s800/MultipleButtonsInTableCell.png) **サンプルコード [#ybe99159] #code(link){{ 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); } } } }} #code{{ 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) { setBackground(isSelected?table.getSelectionBackground():table.getBackground()); return this; } } }} #code{{ 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 ""; } //Copid from AbstractCellEditor //protected EventListenerList listenerList = new EventListenerList(); transient protected ChangeEvent changeEvent = null; @Override public boolean isCellEditable(java.util.EventObject e) { return true; } //...... }} **解説 [#e6806cbc] 上記のサンプルでは、``CellRenderer``用と``CellEditor``用に、``JButton``を2つ配置した``JPanel``をそれぞれ作成しています。アクションイベントを設定するのは、``CellEditor``用の``JButton``で、``CellRenderer``用の``JButton``は表示のためのダミーです。 // %%行の選択状態が切り替わるとき(例えば、一行目を選択していて、二行目のボタンをクリック)には、``CellEditor``用の``JButton``がうまくクリックできないので、``JTable``自体に以下のようなマウスリスナーを設定しています。%% // //#code{{ //class CellButtonsMouseListener extends MouseAdapter{ // @Override public void mouseReleased(MouseEvent e) { // JTable t = (JTable)e.getComponent(); // Point pt = e.getPoint(); // int row = t.rowAtPoint(pt); // int col = t.columnAtPoint(pt); // if(t.convertRowIndexToModel(row)>=0 && t.convertColumnIndexToModel(col)==1) { // TableCellEditor ce = t.getCellEditor(row, col); // ce.stopCellEditing(); // Component c = ce.getTableCellEditorComponent(t, null, true, row, col); // Point p = SwingUtilities.convertPoint(t, pt, c); // Component b = SwingUtilities.getDeepestComponentAt(c, p.x, p.y); // if(b instanceof JButton) ((JButton)b).doClick(); // } // } //} //}} ---- - ``JSpinner``(``JButton``*``2``+``JTextField``)を``CellEditor``に使用する -- [[CellEditorをJSpinnerにして日付を変更>Swing/DateCellEditor]] #code{{ import java.awt.*; import java.awt.event.*; import java.util.*; import java.util.List; import javax.swing.*; import javax.swing.event.*; import javax.swing.table.*; import javax.swing.text.*; public class ButtonsInsideCellTest { private JComponent makeUI() { String[] columnNames = {"Buttons", "Spinner"}; Object[][] data = { {50, 100}, {100, 50}, {30, 20}, {0, 100} }; DefaultTableModel model = new DefaultTableModel(data, columnNames) { @Override public Class<?> getColumnClass(int column) { return getValueAt(0, column).getClass(); } }; JTable table = new JTable(model); table.setRowHeight(36); table.setAutoCreateRowSorter(true); TableColumn column = table.getColumnModel().getColumn(0); column.setCellRenderer(new ButtonsRenderer()); column.setCellEditor(new ButtonsEditor()); column = table.getColumnModel().getColumn(1); column.setCellRenderer(new SpinnerRenderer()); column.setCellEditor(new SpinnerEditor()); return new JScrollPane(table); } 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 ButtonsInsideCellTest().makeUI()); f.setSize(320, 240); f.setLocationRelativeTo(null); f.setVisible(true); } } class SpinnerPanel extends JPanel { public final JSpinner spinner = new JSpinner(new SpinnerNumberModel(100, 0, 200, 1)); public SpinnerPanel() { super(new GridBagLayout()); GridBagConstraints c = new GridBagConstraints(); c.weightx = 1.0; c.insets = new Insets(0, 10, 0, 10); c.fill = GridBagConstraints.HORIZONTAL; setOpaque(true); add(spinner, c); } } class SpinnerRenderer extends SpinnerPanel implements TableCellRenderer { public SpinnerRenderer() { super(); setName("Table.cellRenderer"); } @Override public Component getTableCellRendererComponent( JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { setBackground(isSelected?table.getSelectionBackground():table.getBackground()); spinner.setValue((Integer)value); return this; } } class SpinnerEditor extends SpinnerPanel implements TableCellEditor { // public SpinnerEditor(final JTable table, final int column) { // super(); // } @Override public Component getTableCellEditorComponent( JTable table, Object value, boolean isSelected, int row, int column) { this.setBackground(table.getSelectionBackground()); spinner.setValue((Integer)value); return this; } @Override public Object getCellEditorValue() { //System.out.println("getCellEditorValue: " + spinner.getValue()); //try { // spinner.commitEdit(); //} catch(Exception pe) { // // Edited value is invalid, spinner.getValue() will return // // the last valid value, you could revert the spinner to show that: // JComponent editor = spinner.getEditor(); // if (editor instanceof JSpinner.DefaultEditor) { // ((JSpinner.DefaultEditor)editor).getTextField().setValue(spinner.getValue()); // } //} return spinner.getValue(); } //Copid from AbstractCellEditor //protected EventListenerList listenerList = new EventListenerList(); transient protected ChangeEvent changeEvent = null; @Override public boolean isCellEditable(EventObject e) { return true; } @Override public boolean shouldSelectCell(EventObject anEvent) { return true; } @Override public boolean stopCellEditing() { try { spinner.commitEdit(); } catch(Exception pe) { Toolkit.getDefaultToolkit().beep(); return false; // 直前の値に戻して、編集を終了する場合 // Edited value is invalid, spinner.getValue() will return // the last valid value, you could revert the spinner to show that: //JComponent editor = spinner.getEditor(); //if (editor instanceof JSpinner.DefaultEditor) { // ((JSpinner.DefaultEditor)editor).getTextField().setValue(spinner.getValue()); //} } 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 listenerList.getListeners(CellEditorListener.class); } protected void fireEditingStopped() { // Guaranteed to return a non-null array Object[] listeners = listenerList.getListenerList(); // Process the listeners last to first, notifying // those that are interested in this event for(int i = listeners.length-2; i>=0; i-=2) { if(listeners[i]==CellEditorListener.class) { // Lazily create the event: if(changeEvent == null) changeEvent = new ChangeEvent(this); ((CellEditorListener)listeners[i+1]).editingStopped(changeEvent); } } } protected void fireEditingCanceled() { // Guaranteed to return a non-null array Object[] listeners = listenerList.getListenerList(); // Process the listeners last to first, notifying // those that are interested in this event for(int i = listeners.length-2; i>=0; i-=2) { if(listeners[i]==CellEditorListener.class) { // Lazily create the event: if(changeEvent == null) changeEvent = new ChangeEvent(this); ((CellEditorListener)listeners[i+1]).editingCanceled(changeEvent); } } } } class ButtonsPanel extends JPanel { public final List<JButton> buttons = Arrays.asList(new JButton("+"), new JButton("-")); public final JLabel label = new JLabel() { @Override public Dimension getPreferredSize() { Dimension d = super.getPreferredSize(); d.width = 50; return d; } }; public int i = -1; public ButtonsPanel() { super(); label.setHorizontalAlignment(SwingConstants.RIGHT); setOpaque(true); add(label); 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) { this.setBackground(isSelected?table.getSelectionBackground():table.getBackground()); label.setText(value!=null?value.toString():""); return this; } } class ButtonsEditor extends ButtonsPanel implements TableCellEditor { public ButtonsEditor() { super(); buttons.get(0).addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { i++; label.setText(""+i); fireEditingStopped(); } }); buttons.get(1).addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { i--; label.setText(""+i); fireEditingStopped(); } }); 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()); i = (Integer)value; label.setText(""+i); return this; } @Override public Object getCellEditorValue() { return i; } //Copid from AbstractCellEditor //protected EventListenerList listenerList = new EventListenerList(); transient protected ChangeEvent changeEvent = null; @Override public boolean isCellEditable(EventObject e) { return true; } @Override public boolean shouldSelectCell(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 listenerList.getListeners(CellEditorListener.class); } protected void fireEditingStopped() { // Guaranteed to return a non-null array Object[] listeners = listenerList.getListenerList(); // Process the listeners last to first, notifying // those that are interested in this event for(int i = listeners.length-2; i>=0; i-=2) { if(listeners[i]==CellEditorListener.class) { // Lazily create the event: if(changeEvent == null) changeEvent = new ChangeEvent(this); ((CellEditorListener)listeners[i+1]).editingStopped(changeEvent); } } } protected void fireEditingCanceled() { // Guaranteed to return a non-null array Object[] listeners = listenerList.getListenerList(); // Process the listeners last to first, notifying // those that are interested in this event for(int i = listeners.length-2; i>=0; i-=2) { if(listeners[i]==CellEditorListener.class) { // Lazily create the event: if(changeEvent == null) changeEvent = new ChangeEvent(this); ((CellEditorListener)listeners[i+1]).editingCanceled(changeEvent); } } } } }} **参考リンク [#b4c9d73f] -[[JTableのセルにJButtonを追加して行削除>Swing/DeleteButtonInCell]] -[[JTableのセルにHyperlinkを表示>Swing/HyperlinkInTableCell]] -[http://tips4java.wordpress.com/2009/07/12/table-button-column/ Table Button Column « Java Tips Weblog] -[[JTableのセル中にJRadioButtonを配置>Swing/RadioButtonsInTableCell]] -[[JTableのCellにJCheckBoxを複数配置する>Swing/CheckBoxesInTableCell]] **コメント [#le0df76f] - 第``0``列目が編集状態でボタンをクリックした場合、パネルが二度表示されるバグを修正。 -- [[aterai]] &new{2009-10-06 (火) 11:56:21}; - [http://tips4java.wordpress.com/2009/07/12/table-button-column/ Table Button Column « Java Tips Weblog]を参考にして、``JTable#editCellAt``ではなく、逆に``TableCellEditor#stopCellEditing()``を使用してクリック直後に編集終了するように変更。 -- [[aterai]] &new{2009-11-03 (火) 04:36:55}; - ``Ctrl``キーを押しながら、``edit``ボタンをクリックすると異なる行(``table.getSelectedRow()``)の内容が表示されるバグを修正。 -- [[aterai]] &new{2011-03-10 (木) 02:35:35}; - KBD{Ctrl}キーを押しながら、``edit``ボタンをクリックすると異なる行(``table.getSelectedRow()``)の内容が表示されるバグを修正。 -- [[aterai]] &new{2011-03-10 (木) 02:35:35}; - すごいと思いました! -- [[いわく]] &new{2013-05-24 (金) 11:57:26}; -- こんばんは。たしかに``JTable``の``TableCellRenderer``、``TableCellEditor``の仕組みは、すごい良くできているといつも感心してしまいます :) -- [[aterai]] &new{2013-05-24 (金) 23:59:16}; #comment