Strange DefaultTreeCellRenderer behaviour, only partially executing getTreeCellRendererComponent()

StackOverflow https://stackoverflow.com/questions/10506170

Frage

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).

War es hilfreich?

Lösung 2

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();

Andere Tipps

1) are you tried to notified TreeModel TreeModel.nodeChanged(node); that value changed

2) put Icon(s) directly to the TreeModel, not to re_create inside TreeCellRenderer

3) JTree (JTable, JList and JList from JComboBox) to share the same concept as Renderer for JTable

4) please to read Customizing a Tree's Display

5) examples here and here

I'm glad you figured out the try-catch part. To solve the problem, make sure you are not supplying your DefaultTreeModel anything other than an instance of TreeItem. You should put this line System.out.println(value.getClass()) in your catch block.

Also, you should consider creating a single instance of your Icons instead of making a new one each time a tree node is expanded or collapsed.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top