Swing/AddRemoveTableColumn のバックアップ(No.3)
- バックアップ一覧
- 差分 を表示
- 現在との差分 を表示
- 現在との差分 - Visual を表示
- ソース を表示
- Swing/AddRemoveTableColumn へ行く。
- 1 (2019-12-16 (月) 17:04:15)
- 2 (2019-12-17 (火) 02:32:43)
- 3 (2020-10-31 (土) 00:19:04)
- 4 (2022-08-30 (火) 21:02:15)
- category: swing folder: AddRemoveTableColumn title: JTableHeaderに追加された各TableColumnの表示・非表示を切り替える tags: [JTable, JTableHeader, TableColumn, TableColumnModel, JPopupMenu, JCheckBoxMenuItem] author: aterai pubdate: 2019-12-16T16:53:12+09:00 description: JTableHeaderのTableColumnが表示・非表示状態かをJCheckBoxMenuItemを使用して切り替えます。 image: https://drive.google.com/uc?id=1s7b9r9oP8o0El5Ti3e1xM84anoj5r_Te
概要
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