Search code examples
javaswingjtreerepainttreemodel

Updating ImageIcon in JTree without repainting the Tree?


Basically I edit an attribute private string status="OK" in the UserObject() of a DefaultTreeNode().

I have a CustomRenderer which implements DefaultCellRenderer, which sets the Icon by rendering the "OK" attribute of UserObject of a TreeNode.

Originally, when I select a node, the icon changes. I am using Tree.revalidate() & Tree.repaint(), and the change is being reflected.

However, I am not sure if this very efficient. What would be the proper way of doing this? I tried doing TreeModel.nodesChanged(new DefaultMutableTreeNode(myUserObject)) but the TreeNodeChanged event will not fire.

So am I stuck to using repainting the entire tree everytime a userboject of a TreeNode is changed to see the graphic update?


Solution

  • Use the approach shown in TreeIconDemo2 to condition the renderer based on the model's value. For example,

    private class MyRenderer extends DefaultTreeCellRenderer {
    
        private Icon okIcon;
    
        public MyRenderer(Icon okIcon) {
            this.okIcon = okIcon;
        }
    
        @Override
        public Component getTreeCellRendererComponent(JTree tree, Object value,
            boolean sel, boolean exp, boolean leaf, int row, boolean hasFocus) {
            super.getTreeCellRendererComponent(
                tree, value, sel, exp, leaf, row, hasFocus);
            YourMutableTreeNode node = (YourMutableTreeNode) value;
            if (leaf && node.getStatus().equals("OK")) {
                setIcon(okIcon);
            }
            return this;
        }
    }
    

    Addendum: You can't simply invoke nodeChanged() on a new TreeNode that's not part of the tree; the new node has no parent. If you specify an existing node to nodeChanged(), the notification will happen automatically. If needed, there's an example of searching a tree here.