概要

JTableの各行に配置したJCheckBoxが選択されている場合、その行を別のJTableに表示するRowFilterを作成します。

サンプルコード

TableModel model = new DefaultTableModel(data, columnNames) {
  @Override public Class<?> getColumnClass(int column) {
    return getValueAt(0, column).getClass();
  }
};
JTable selector = new JTable(model);
selector.setAutoCreateRowSorter(true);
selector.getColumnModel().getColumn(0).setMaxWidth(32);

JTable viewer = new JTable(model) {
  @Override public boolean isCellEditable(int row, int column) {
    return false;
  }
};
viewer.setAutoCreateRowSorter(true);
TableColumnModel cm = viewer.getColumnModel();
cm.removeColumn(cm.getColumn(0));

TableRowSorter<TableModel> sorter = new TableRowSorter<>(model);
viewer.setRowSorter(sorter);
sorter.setRowFilter(new RowFilter<TableModel, Integer>() {
  @Override public boolean include(
      Entry<? extends TableModel, ? extends Integer> entry) {
    return Objects.equals(entry.getModel().getValueAt(
        entry.getIdentifier(), 0), Boolean.TRUE);
  }
});
model.addTableModelListener(e -> {
  if (e.getType() == TableModelEvent.UPDATE) {
    sorter.allRowsChanged();
    // sorter.modelStructureChanged();
  }
});
View in GitHub: Java, Kotlin

解説

上記のサンプルでは、選択用と表示用の2つのJTableを作成しています。どちらのJTableもモデルは同じものを共有していますが、以下のような異なる設定をしています。

  • 選択用のJTable:
    • 0列目の値(Boolean)をJCheckBoxで編集可能になるよう設定
  • 表示用のJTable:
    • JTable#isCellEditable(...)をオーバーライドしてモデルではなくJTable側で編集不可を設定
    • Boolean値を持つモデルの0列目(表示はJCheckBox)をTableColumnModel#removeColumn(...)メソッドで非表示に設定
    • RowFilter#include(...)をオーバーライドして0列目の値がBoolean.TRUEの場合はその行を表示するRowFilterを作成して設定
  • 共有のTableModel:
    • TableModelListenerを設定し、JCheckBoxの選択などでモデルが更新された場合はTableRowSorter#allRowsChanged()を実行してフィルタリングの更新を行う

参考リンク

コメント