TITLE:JTableのセルに複数のJButtonを配置する

Posted by aterai at 2009-10-05

JTableのセルに複数のJButtonを配置する

JTableのセル内にクリック可能な複数のJButtonを配置します。

  • &jnlp;
  • &jar;
  • &zip;
MultipleButtonsInTableCell.png

サンプルコード

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) {
    setBackground(isSelected?table.getSelectionBackground():table.getBackground());
    return this;
  }
}
class ButtonsEditor extends ButtonsPanel
                    implements TableCellEditor {
  public ButtonsEditor(final JTable table) {
    super();
    MouseListener ml = new MouseAdapter() {
      public void mousePressed(MouseEvent e) {
        ButtonModel m = ((JButton)e.getSource()).getModel();
        if(m.isPressed() && table.isRowSelected(table.getEditingRow())
                         && !e.isShiftDown()) {
          setBackground(table.getBackground());
        }
      }
    };
    buttons.get(0).addActionListener(new ActionListener() {
      @Override public void actionPerformed(ActionEvent e) {
        fireEditingStopped();
        JOptionPane.showMessageDialog(table, "Viewing");
      }
    });
    buttons.get(0).addMouseListener(ml);
    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);
      }
    });
    buttons.get(1).addMouseListener(ml);
    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;
  }
//......

解説

上記のサンプルでは、CellRenderer用とCellEditor用に、JButtonを2つ配置したJPanelをそれぞれ作成しています。アクションイベントを設定するのは、CellEditor用のJButtonで、CellRenderer用のJButtonは表示のためのダミーです。

行の選択状態が切り替わるとき(例えば、一行目を選択していて、二行目のボタンをクリック)には、CellEditor用のJButtonがうまくクリックできないので、JTable自体に以下のようなマウスリスナーを設定しています。

参考リンク

コメント

  • 第0列目が編集状態でボタンをクリックした場合、パネルが二度表示されるバグを修正。 -- aterai
  • Table Button Column « Java Tips Weblogを参考にして、JTable#editCellAtではなく、逆にTableCellEditor#stopCellEditing()を使用するように変更しました。 -- aterai
  • Ctrlキーを押しながら、editボタンをクリックすると異なる行(table.getSelectedRow())の内容が表示されるバグを修正。 -- aterai