Search code examples
javaswingjtreetreecellrenderer

Strange DefaultTreeCellRenderer behaviour, only partially executing getTreeCellRendererComponent()


I created a JTree, even with multiple root nodes (what was quite hard for me, as it's my first JTree), and was ready (I thought) to go one step further; a cellrenderer.

I tried to set one icon for every node, it worked fine. Now I'm trying to check what kind of node it is (not only leaf and branch), and building a String of the filename of the image I want. isKlas() always returns true for now, so it should be klas_fold.png OR klas_unfold.png. BUT the getTreeCellRendererComponent() is only partially executed because the filepath never gets printed, nor is any icon changed, it's always the default!

Here's my code:

import javax.swing.*;
import javax.swing.tree.*;
import java.awt.*;

public class RATree extends JTree {

    private static final long serialVersionUID = -3855798479619346917L;

    public RATree(Object[] top) {
        super(top);
        MyRenderer renderer = new MyRenderer();
        this.setCellRenderer(renderer);

        setBorder(BorderFactory.createRaisedBevelBorder());
    }

    protected ImageIcon createImageIcon(String path) {

        java.net.URL imgURL = getClass().getResource(path);
        if (imgURL != null) {
            return new ImageIcon(imgURL);
        } else {
            System.err.println("Couldn't find file: " + path);
            return null;
        }
    }

    class MyRenderer extends DefaultTreeCellRenderer {

        public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) {
            TreeItem node;
            String fileName = "";
            super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
            try {
                node = (TreeItem) value;
            }
            catch (ClassCastException ex)
            {
                ex.printStackTrace();
                return this;
            }

            if(node.isKlas()) {
                fileName += "klas_";
            }

            if(expanded) {
                fileName += "unfold.png";
                this.setIcon(createImageIcon("../bin/" + fileName));
            }
            else {
                fileName += "fold.png";
                this.setIcon(createImageIcon("../bin/" + fileName));
            }

            System.out.println("fileName: " + fileName); //Doesn't get executed, or at least, I can't see it.
            return this;
        }

    }
    public static void main(String[] args) {
        JFrame f = new JFrame("Short, Self Contained, Correct (Compilable), Example");
        Object[] root = {new TreeItem("name", "someURL"), new TreeItem("name", "someUrl")};
        f.add(new RATree(root));
        f.setSize(100,100);
        f.setVisible(true);
    }
}

Yes, it's an inner class.

Thanks!

EDIT:

I found out it was a ClassCastException that screwed things. But that's strange, because I initialize the Tree like this: new JTree({new TreeItem("params"), new TreeItem("params")});. So I should be able to cast them back from Object to TreeItem? (TreeItem iis one of my classes. It extends DefaultMutableTreeNode).


Solution

  • I solved it myself! I thought that Object value was the TreeItem I put in the JTree, but it was something else. I got the TreeItem by doing this (like in the Customizing a Tree's display link supplied by mKorbel):

    TreeItem node = (TreeItem) ((DefaultMutableTreeNode)value).getUserObject();