Summary
TreeModelから親JCheckBoxと子JCheckBoxのグループを作成し、親JCheckBoxが選択されている場合のみ子JCheckBoxのグループを有効化します。
Screenshot

Advertisement
Source Code Examples
class CheckBoxStatusUpdateListener implements TreeModelListener {
private boolean adjusting;
@Override public void treeNodesChanged(TreeModelEvent e) {
if (adjusting) {
return;
}
adjusting = true;
DefaultTreeModel model = (DefaultTreeModel) e.getSource();
Object[] children = e.getChildren();
boolean isOnlyOneNodeSelected = Objects.nonNull(children) && children.length == 1;
Object current = isOnlyOneNodeSelected ? children[0] : model.getRoot();
if (current instanceof DefaultMutableTreeNode) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode) current;
CheckBoxNode c = (CheckBoxNode) node.getUserObject();
for (Object child : e.getChildren()) {
updateAllChildrenUserObject((DefaultMutableTreeNode) child, c.selected);
}
model.nodeChanged((DefaultMutableTreeNode) e.getTreePath().getLastPathComponent());
}
adjusting = false;
}
private void updateAllChildrenUserObject(DefaultMutableTreeNode parent, boolean enabled) {
// Java 9: Collections.list(parent.breadthFirstEnumeration()).stream()
Collections.list((Enumeration<?>) parent.breadthFirstEnumeration()).stream()
.filter(DefaultMutableTreeNode.class::isInstance)
.map(DefaultMutableTreeNode.class::cast)
.filter(node -> !Objects.equals(parent, node))
.forEach(node -> {
CheckBoxNode check = (CheckBoxNode) node.getUserObject();
node.setUserObject(new CheckBoxNode(check.text, check.selected, enabled));
});
}
@Override public void treeNodesInserted(TreeModelEvent e) {
/* not needed */
}
@Override public void treeNodesRemoved(TreeModelEvent e) {
/* not needed */
}
@Override public void treeStructureChanged(TreeModelEvent e) {
/* not needed */
}
}
View in GitHub: Java, KotlinDescription
BoxBox.createVerticalBox()で作成した垂直BoxにJCheckBoxを配置して作成- フォルダノードを親
JCheckBox、葉ノードを子JCheckBoxのグループとして作成 - 子
JCheckBoxはBox.createHorizontalBox()にBox.createHorizontalStrut( (DefaultMutableTreeNode#getLevel() - 1) * 16))で作成したインデントと合わせて追加してから垂直Boxに配置 - 親
JCheckBoxにActionListenerを追加し、選択状態で子JCheckBoxのグループの有効化・無効化を切り替える- どの親
JCheckBoxの子JCheckBoxかはDefaultMutableTreeNode#children()で名前を取得して検索しているので、同名ノードが存在すると正しく動作しない
- どの親
JTreeTreeCellRendererとTreeCellEditorでJCheckBoxを使用するよう設定TreeWillExpandListenerを追加してノードの折り畳みを無効化TreeModelListenerを追加してフォルダノードから作成した親JCheckBoxの選択状態が変更されたら葉ノードから作成された子JCheckBoxの有効化・無効化を切り替える- 孫ノードから作成された
JCheckBoxの有効化・無効化は考慮していない