简体   繁体   中英

How to disable expand sign in Swing JTree?

I'm working in Swing and I would like to disable the expand (plus [+]) sign on a certain type of nodes.

Not sure how to do it because my nodes aren't leaves and I also cannot use setShowsRootHandles (which is only for the root).

I'm referring to to JTree: suppose i got this structure:

Root

--[+] node1

--[+] node2

when I load this structure i would like not to see the [+] sign on node2 (because it a special type node). But I also would like to expand it by using a special command.

I've overridden isLeaf() (method from DefaultMutableTreeNode) so it would set to to TRUE when i'm in the special type node, but then when I'm trying to expand it, it wouldn't expand because isLeaf() == TRUE...

Hope this will make things more clear.

While it is not possible to remove the handles, it is possible to restrict the expansion of nodes. The way to go is a TreeWillExpandListener combined with a custom treeNode that has state to restrict expansion:

  • the custom node below has an expandable property that's false by default
  • when detecting custom nodes, the listener allows/vetoes expansion based on that expandable property
  • for programmatic expansion, the expandable property is set to true temporarily to pass the listener

Example code:

// mixed tree of normal/restricted noded
DefaultMutableTreeNode root = new DefaultMutableTreeNode("root");
DefaultMutableTreeNode normalSubTree = new DefaultMutableTreeNode("normal");
normalSubTree.add(new DefaultMutableTreeNode("normalChild"));
MyNode restrictedSubTree = new MyNode("restrictedSubtree");
restrictedSubTree.add(new DefaultMutableTreeNode("restrictedChild"));
root.add(normalSubTree);
root.add(restrictedSubTree);
final JTree tree = new JTree(root);
// the listener which vetos expansion of MyNodes that are not expandable
TreeWillExpandListener l = new TreeWillExpandListener() {

    @Override
    public void treeWillExpand(TreeExpansionEvent event)
            throws ExpandVetoException {
        TreePath path = event.getPath();
        if (path.getLastPathComponent() instanceof MyNode) {
            if (!((MyNode) path.getLastPathComponent()).isExpandable()) {
                throw new ExpandVetoException(event, "node not expandable");
            }
        }
    }

    @Override
    public void treeWillCollapse(TreeExpansionEvent event)
            throws ExpandVetoException {
    }
};
tree.addTreeWillExpandListener(l);

Action expand = new AbstractAction("Expand") {

    @Override
    public void actionPerformed(ActionEvent e) {
        TreePath selected = tree.getSelectionPath();
        if (selected == null) return;
        if (selected.getLastPathComponent() instanceof MyNode) {
            MyNode last = (MyNode) selected.getLastPathComponent();
            boolean old = last.isExpandable();
            last.setExpandable(true);
            tree.expandPath(selected);
            last.setExpandable(old);
        }
    }
};

    JXFrame frame = wrapWithScrollingInFrame(tree, "veto expand");
    addAction(frame, expand);
    show(frame);
}

// custom node which has an expandable property
public static class MyNode extends DefaultMutableTreeNode {

    private boolean expandable;

    public MyNode() {
        this(null);
    }

    public MyNode(Object userObject) {
        super(userObject);
    }

    public void setExpandable(boolean expandable) {
        this.expandable = expandable;
    }

    public boolean isExpandable() {
        return expandable;
    }
}

It's possible to remove the handles - despite what others have mentioned. I've attached a snippet on how to do this below. The key thing is to override shouldPaintExpandControl in BasicTreeUI .

jtree.setUI(new BasicTreeUI() {
    @Override
    protected boolean shouldPaintExpandControl(final TreePath path, final int row
            , final boolean isExpanded, final boolean hasBeenExpanded, final boolean isLeaf)
    {
        boolean shouldDisplayExpandControl = false;
        return shouldDisplayExpandControl;
    }

This should really be documented in the JTree API but that's another issue.


Another approach to consider:

If you call DefaultTreeModel(TreeNode root, boolean asksAllowsChildren) the model will "ask" the nodes you insert if they are allowed to have children. If they cannot, it should not display the expand icon.

Be sure to override javax.swing.tree.TreeNode.getAllowsChildren() in your class.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM