JTableHeaderに追加された各TableColumnの表示・非表示を切り替える
Total: 3652
, Today: 3
, Yesterday: 0
Posted by aterai at
Last-modified:
概要
JTableHeader
のTableColumn
が表示・非表示状態かをJCheckBoxMenuItem
を使用して切り替えます。
Screenshot
Advertisement
サンプルコード
class TableHeaderPopupMenu extends JPopupMenu {
protected TableHeaderPopupMenu(JTable table) {
super();
TableColumnModel columnModel = table.getColumnModel();
List<TableColumn> list = Collections.list(columnModel.getColumns());
list.forEach(tableColumn -> {
String name = Objects.toString(tableColumn.getHeaderValue());
// System.out.format("%s - %s%n", name, tableColumn.getIdentifier());
JCheckBoxMenuItem item = new JCheckBoxMenuItem(name, true);
item.addItemListener(e -> {
if (((AbstractButton) e.getItemSelectable()).isSelected()) {
columnModel.addColumn(tableColumn);
} else {
columnModel.removeColumn(tableColumn);
}
updateMenuItems(columnModel);
});
add(item);
});
}
@Override public void show(Component c, int x, int y) {
if (c instanceof JTableHeader) {
JTableHeader header = (JTableHeader) c;
JTable table = header.getTable();
header.setDraggedColumn(null);
header.repaint();
table.repaint();
updateMenuItems(header.getColumnModel());
super.show(c, x, y);
}
}
private void updateMenuItems(TableColumnModel columnModel) {
boolean isOnlyOneMenu = columnModel.getColumnCount() == 1;
if (isOnlyOneMenu) {
stream(this).map(MenuElement::getComponent).forEach(mi ->
mi.setEnabled(!(mi instanceof AbstractButton)
|| !((AbstractButton) mi).isSelected()));
} else {
stream(this).forEach(me -> me.getComponent().setEnabled(true));
}
}
private static Stream<MenuElement> stream(MenuElement me) {
return Stream.of(me.getSubElements())
.flatMap(m -> Stream.concat(Stream.of(m), stream(m)));
}
}
View in GitHub: Java, Kotlin解説
- 初期状態では
TableModel
から生成されたTableColumn
がすべて表示されているJCheckBoxMenuItem
もすべて選択状態になる
JCheckBoxMenuItem
で選択解除されたらTableColumnModel#removeColumn(TableColumn)
メソッドでTableColumn
を非表示TableColumnModel
から列は削除されてJTableHeader
からは非表示になるが、TableModel
のその列はそのまま残っているTableColumn
がすべて非表示にならないよう、JPopupMenu
を開くときなどにその列数をチェックしてJCheckBoxMenuItem
の選択可・不可を切り替えている
JCheckBoxMenuItem
で選択設定されたらTableColumnModel#addColumn(TableColumn)
メソッドでTableColumn
を表示TableColumnModel
に列は追加されてJTableHeader
にも表示されるが、TableModel
は初期状態から変化しない
Java 9
以上で有効なUIManager.put("CheckBoxMenuItem.doNotCloseOnMouseClick", true)
を設定し、JPopupMenu
を開いたまま現在選択状態のTableColumn
をJCheckBoxMenuItem
で非表示に切り替えるとArrayIndexOutOfBoundsException
が発生するPopupMenuListener
をJPopupMenu
に追加、またはJPopupMenu#show(...)
メソッドをオーバーライドしてJTableHeader.setDraggedColumn(null)
で選択状態をクリアすれば回避が可能
参考リンク
- JTableHeaderにJPopupMenuを追加してソート
- JCheckBoxMenuItemをクリックしてもJPopupMenuを閉じないように設定する
- JTableのColumn名を変更する
- Table Column Manager « Java Tips Weblog