JTableHeaderに追加された各TableColumnの表示・非表示を切り替える
Total: 4275, Today: 1, Yesterday: 3
Posted by aterai at
Last-modified:
Summary
JTableHeaderのTableColumnが表示・非表示状態かをJCheckBoxMenuItemを使用して切り替えます。
Screenshot

Advertisement
Source Code Examples
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, KotlinDescription
- 初期状態では
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)で選択状態をクリアすれば回避が可能
Reference
- JTableHeaderにJPopupMenuを追加してソート
- JCheckBoxMenuItemをクリックしてもJPopupMenuを閉じないように設定する
- JTableのColumn名を変更する
- Table Column Manager « Java Tips Weblog