TITLE:JTableのセルにJButtonを追加して行削除

Posted by at 2007-10-22

JTableのセルにJButtonを追加して行削除

`JTableのセルにJButton`を追加し、クリックされたらその行を削除します。主にSwing - JButton inside JTable Cellの投稿を参考にしています。

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

サンプルコード

class DeleteButton extends JButton {
  @Override public void updateUI() {
    super.updateUI();
    setBorder(BorderFactory.createEmptyBorder());
    setFocusable(false);
    setRolloverEnabled(false);
    setText("X");
  }
}
View in GitHub: Java, Kotlin
class DeleteButtonRenderer extends DeleteButton implements TableCellRenderer {
  public DeleteButtonRenderer() {
    super();
    setName("Table.cellRenderer");
  }
  @Override public Component getTableCellRendererComponent(JTable table,
      Object value, boolean isSelected, boolean hasFocus, int row, int column) {
    return this;
  }
}
class DeleteButtonEditor extends DeleteButton implements TableCellEditor {
  public DeleteButtonEditor(final JTable table) {
    super();
    addActionListener(new ActionListener() {
      @Override public void actionPerformed(ActionEvent e) {
        int row = table.convertRowIndexToModel(table.getEditingRow());
        fireEditingStopped();
        ((DefaultTableModel)table.getModel()).removeRow(row);
      }
    });
  }
  @Override public Component getTableCellEditorComponent(JTable table,
      Object value, boolean isSelected, int row, int column) {
    return this;
  }
  @Override public Object getCellEditorValue() {
    return "";
  }
  //Copid from AbstractCellEditor
  //protected EventListenerList listenerList = new EventListenerList();
  //transient protected ChangeEvent changeEvent = null;
//......

解説

上記のサンプルでは、ボタンがクリックされたときの削除自体は、`JTableに追加したマウスリスナーで行っており、セルエディタやセルレンダラーに使っているJButton`は表示のためのダミーです。

  • セルレンダラーに使っている`JButton`は表示のためのダミー
  • セルエディタとして使用する`JButtonActionListenerを追加し、クリックされたらAbstractCellEditorからコピーしたfireEditingStopped()メソッドで編集を終了し、TableModel`から行を削除
    • セルレンダラ、セルエディタがコンポーネント(もしくは`DefaultCellEditor)を継承していないと、JTableLookAndFeelを変更てもセルレンダラ、セルエディタのupdateUI()`が呼ばれない
      • `JTable#updateUI()Java 1.6.0JTable#updateSubComponentUI(...)Java 1.7.0SwingUtilities#updateRendererOrEditorUI(Object)`を参照
    • `AbstractCellEditorを継承していてもupdateUI()は呼ばれない、DefaultCellEditor`は継承しづらい…

参考リンク

コメント

//上記のBug Databaseにある回避方法
JTable table = new JTable(model) {
  @Override public int rowAtPoint(Point pt) {
    return (pt.y<0)?-1:super.rowAtPoint(pt);
  }
};