TITLE:JTableのセルに複数のJButtonを配置する
#navi(../)
RIGHT:Posted by [[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{{
class ButtonsEditorRenderer extends AbstractCellEditor
                            implements TableCellRenderer,TableCellEditor{
  private final JPanel renderer = new JPanel();
  private final JPanel editor   = new JPanel();
  private final JTable table;
  private final MouseListener ml = new MouseAdapter() {
    public void mousePressed(MouseEvent e) {
      ButtonModel m = ((JButton)e.getSource()).getModel();
      if(m.isPressed() && table.isRowSelected(table.getEditingRow())
         && !e.isShiftDown()) {
        editor.setBackground(table.getBackground());
      }
    }
  };
  public ButtonsEditorRenderer(JTable t) {
    super();
    this.table = t;
    JButton viewButton2 = new JButton(new AbstractAction("view") {;
      @Override public void actionPerformed(ActionEvent e) {
        fireEditingStopped();
        JOptionPane.showMessageDialog(table, "Viewing");
      }
    });
    JButton editButton2 = new JButton(new AbstractAction("edit") {;
      @Override public void actionPerformed(ActionEvent e) {
        //if isControlDown bug:
        //Object o = table.getModel().getValueAt(table.getSelectedRow(), 0);
        int row = table.convertRowIndexToModel(table.getEditingRow());
        Object o = table.getModel().getValueAt(row, 0);
        fireEditingStopped();
        JOptionPane.showMessageDialog(table, "Editing: "+o);
      }
    });
    viewButton2.addMouseListener(ml);
    viewButton2.setFocusable(false);
    viewButton2.setRolloverEnabled(false);

    editButton2.addMouseListener(ml);
    editButton2.setFocusable(false);
    editButton2.setRolloverEnabled(false);

    renderer.setOpaque(true);
    renderer.add(new JButton("view"));
    renderer.add(new JButton("edit"));
    editor.setOpaque(true);
    editor.add(viewButton2);
    editor.add(editButton2);
    editor.addMouseListener(new MouseAdapter() {
      @Override public void mousePressed(MouseEvent e) {
        fireEditingStopped();
      }
    });
  }
  @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 "";
  }
}
}}

**解説 [#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();
//    }
//  }
//}
//}}

**参考リンク [#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};

#comment