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

Posted by aterai at 2009-10-05

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

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

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

サンプルコード

class ButtonsEditorRenderer extends AbstractCellEditor
                            implements TableCellRenderer,TableCellEditor{
  private final JPanel renderer = new JPanel();
  private final JPanel editor   = new JPanel();
  public ButtonsEditorRenderer(final JTable table) {
    super();
    JButton viewButton2 = new JButton(new AbstractAction("view2") {;
      @Override
      public void actionPerformed(ActionEvent e) {
        JOptionPane.showMessageDialog(table, "Viewing");
      }
    });
    JButton editButton2 = new JButton(new AbstractAction("edit2") {;
      @Override
      public void actionPerformed(ActionEvent e) {
        //int row = table.convertRowIndexToModel(table.getSelectedRow());
        int row = table.getSelectedRow();
        Object o = table.getModel().getValueAt(row, 0);
        JOptionPane.showMessageDialog(table, "Editing: "+o);
      }
    });
    renderer.setOpaque(true);
    renderer.add(new JButton("view1"));
    renderer.add(new JButton("edit1"));
    editor.setOpaque(true);
    editor.add(viewButton2);
    editor.add(editButton2);
  }
  @Override
  public Component getTableCellRendererComponent(
    JTable table, Object value, boolean isSelected, boolean hasFocus,
    int row, int column) {
    renderer.setBackground(isSelected?table.getSelectionBackground()
                                     :table.getBackground());
    return renderer;
  }
  @Override
  public Component getTableCellEditorComponent(
    JTable table, Object value, boolean isSelected, int row, int column) {
    editor.setBackground(table.getSelectionBackground());
    return editor;
  }
  @Override
  public Object getCellEditorValue() {
    return "";
  }
}

解説

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


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

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();
    }
  }
}

参考リンク

コメント

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