Search code examples
javaswingcheckboxjtree

Select parent node only if all children are selected in Swing


I am developing an IntelliJ plugin will popup dialog to check values from CheckboxTree. for that I am following below Q&A:

Java Swing: Need a good quality developed JTree with checkboxes

But when I click on single child node the parent node is also getting selected. But I want to select parent node only when all its child are selected otherwise unselected.


Solution

  • Just add this code

    Comment the code like below in updatePredecessorsWithCheckMode function and add the code after the for loop

    // If at least one child is selected, selecting also the parent
    //            if (childCheckedNode.isSelected) {
    //                parentCheckedNode.isSelected = true;
    //            }
            }
       //check the parent if all children are selected
        if (parentCheckedNode.allChildrenSelected) {
            parentCheckedNode.isSelected = true;
        }
    

    Full function for reference

    // When a node is checked/unchecked, updating the states of the predecessors
    protected void updatePredecessorsWithCheckMode(TreePath tp, boolean check) {
        TreePath parentPath = tp.getParentPath();
        // If it is the root, stop the recursive calls and return
        if (parentPath == null) {
            return;
        }
        CheckedNode parentCheckedNode = nodesCheckingState.get(parentPath);
        DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode) parentPath.getLastPathComponent();
        parentCheckedNode.allChildrenSelected = true;
        parentCheckedNode.isSelected = false;
        for (int i = 0; i < parentNode.getChildCount(); i++) {
            TreePath childPath = parentPath.pathByAddingChild(parentNode.getChildAt(i));
            CheckedNode childCheckedNode = nodesCheckingState.get(childPath);
            // It is enough that even one subtree is not fully selected
            // to determine that the parent is not fully selected
            if (!childCheckedNode.allChildrenSelected) {
                parentCheckedNode.allChildrenSelected = false;
            }
            // If at least one child is selected, selecting also the parent
           // if (childCheckedNode.isSelected) {
            //    parentCheckedNode.isSelected = true;
           // }
        }
       //check the parent if all children are selected
        if (parentCheckedNode.allChildrenSelected) {
            parentCheckedNode.isSelected = true;
        }
        if (parentCheckedNode.isSelected) {
            checkedPaths.add(parentPath);
        } else {
            checkedPaths.remove(parentPath);
        }
        // Go to upper predecessor
        updatePredecessorsWithCheckMode(parentPath, check);
    }