概要
TreeModel
から親JCheckBox
と子JCheckBox
のグループを作成し、親JCheckBox
が選択されている場合のみ子JCheckBox
のグループを有効化します。
Screenshot
Advertisement
サンプルコード
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, Kotlin解説
Box
Box.createVerticalBox()
で作成した垂直Box
にJCheckBox
を配置して作成- フォルダノードを親
JCheckBox
、葉ノードを子JCheckBox
のグループとして作成 - 子
JCheckBox
はBox.createHorizontalBox()
にBox.createHorizontalStrut( (DefaultMutableTreeNode#getLevel() - 1) * 16))
で作成したインデントと合わせて追加してから垂直Box
に配置 - 親
JCheckBox
にActionListener
を追加し、選択状態で子JCheckBox
のグループの有効化・無効化を切り替える- どの親
JCheckBox
の子JCheckBox
かはDefaultMutableTreeNode#children()
で名前を取得して検索しているので、同名ノードが存在すると正しく動作しない
- どの親
JTree
TreeCellRenderer
とTreeCellEditor
でJCheckBox
を使用するよう設定TreeWillExpandListener
を追加してノードの折り畳みを無効化TreeModelListener
を追加してフォルダノードから作成した親JCheckBox
の選択状態が変更されたら葉ノードから作成された子JCheckBox
の有効化・無効化を切り替える- 孫ノードから作成された
JCheckBox
の有効化・無効化は考慮していない