Code
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)));
}
}
Explanation
- Initially shows all
TableColumn
s generated from a TableModel
- All
JCheckBoxMenuItem
s are also selected
TableColumn
hidden with TableColumnModel#removeColumn(TableColumn)
method when deselected with JCheckBoxMenuItem
- The column is removed from
TableColumnModel
and hidden from JTableHeader
, but the column remains in TableModel
- Check the number of
TableColumn
columns to enable/disable the JCheckBoxMenuItem
, e.g. when opening a JPopupMenu
, so that all TableColumn
s are not hidden
- Show
TableColumn
with TableColumnModel#addColumn(TableColumn)
method when selected and set with JCheckBoxMenuItem
- Columns are added to
TableColumnModel
and appear in JTableHeader
, but TableModel
is unchanged from its initial state
UIManager.put("CheckBoxMenuItem.doNotCloseOnMouseClick", true)
in Java 9 or higher; If set to and the currently selected TableColumn is hidden with JCheckBoxMenuItem
while JPopupMenu
is open, an ArrayIndexOutOfBoundsException
will occur
- Add
PopupMenuListener
to JPopupMenu
or override the JPopupMenu#show(...)
method to JTableHeader.setDraggedColumn(null)
can be avoided by clearing the selection state in the scene view
References
No comments:
Post a Comment