javaswingnodesjtreetreecellrenderer

DefaultTreeCellRenderer not working as expected


I'm being crazy because I don't understand what I'm doing wrong. I need that each node of my Tree have a different icon as if it is correct, incorrect or needs updating. I saw the Oracle Documentation and a lot of webpages (including Stackoverflow) but my Code just show all the nodes with the same icon. I'm sorry if I did something wrong, it's my first POST :>

Display: I can't show because i no have reputation >.<

Imagine a tree and imagine that it show always the leafIcon with the gifNew icon. It seems as if only the state would listen to the last node.

Here's the code (all the vars are correctly created, icons like gifNew too):

ICONS:

static Icon closedIcon = new ImageIcon("folder.png");
    static Icon openIcon = new ImageIcon("folder.png");
    static Icon leafIcon = new ImageIcon("file.png");
    static Icon gifWarn = new ImageIcon("warn.gif");
    static Icon gifOk = new ImageIcon("ok.gif");
    static Icon gifNew = new ImageIcon("plus.gif");
    static Icon gifError = new ImageIcon("error.gif");

Call:

tree.setCellRenderer(new TreeRenderer());

Renderer:

private static class TreeRenderer extends DefaultTreeCellRenderer {


        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);
            DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
            String s = node.getUserObject().toString();
            String error;
            if (actualTree.equals("DOORS")){
                error = checkTypeError(s, valuesClass.listOfValuesDOORS);
                //System.out.println("DOORS - S: "+s);
            }else{
                error = checkTypeError(s, valuesClass.listOfValuesTC);
                //System.out.println("TC - S: "+s);
            }

            switch (error) {
                case "CORRECT":
                    setOpenIcon(openIcon);
                    setClosedIcon(closedIcon);
                    setLeafIcon(leafIcon);
                    break;
                case "CREATE":
                    setOpenIcon(gifNew);
                    setClosedIcon(gifNew);
                    setLeafIcon(gifNew);
                    break;
                case "DELETE":
                    setOpenIcon(gifError);
                    setClosedIcon(gifError);
                    setLeafIcon(gifError);
                    break;
                case "UPDATE":
                    setOpenIcon(gifWarn);
                    setClosedIcon(gifWarn);
                    setLeafIcon(gifWarn);
                    break;
                default:
                    setOpenIcon(openIcon);
                    setClosedIcon(closedIcon);
                    setLeafIcon(leafIcon);
                    //System.err.println("ERROR IN RENDERER. VALUE: "+error);
                    break;
            }

            return this;
        }

        /*****************************************
        * Function that return which error have the actual node to push the icon when the tree is created.
        *****************************************/
        protected static String checkTypeError(String txt, List<valuesClass> list){

            for (int i = 0; i < list.size(); i++) {
                if (list.get(i).text.equals(txt))
                    if (list.get(i).create == true){
                        return "CREATE";
                    }else if (list.get(i).delete == true){
                        return "DELETE";
                    }else if (list.get(i).update == true){
                        return "UPDATE";
                    }else{

                        return "CORRECT";
                    }
            }
            return "DEFAULT";
        }
    }

Solution

  • The behaviour you are describing is caused by the fact that you are not setting correctly the node icon in the switch statement. The setOpenIcon(), setClosedIcon() etc set the icons that the renderer will use for the whole tree. So the action taken in the last node is going to decide what icons will be rendered at the end.

    The DefaultTreeCellRenderer extends a JLabel. This component will be used for each node to render its contents. It is this components' icon that needs to be set i.e. your code should look like this:

    switch (error) {
      case "CORRECT":
           setIcon(leafIcon); // sets the icon of the renderer which is a JLabel
           break;
      case "CREATE":
           setIcon(gifNew);
           break;
      case "DELETE":
           setIcon(gifError);
           break;
      ...
    }
    

    Be sure to set the icon in all cases though and make sure that you understand how the renderer is used to render tree nodes (the same instance is reused for all nodes)