Странное поведение DefaultTreeCellRenderer, только частично выполняющее getTreeCellRendererComponent()

Я создал JTree, даже с несколькими корневыми узлами (что было довольно сложно для меня, так как это мой первый JTree), и был готов (я думал) пойти еще дальше; сотовый торговец.

Я пытался установить один значок для каждого узла, он работал нормально. Теперь я пытаюсь проверить, что это за узел (не только лист и ветвь), и строю строку с именем файла изображения, которое я хочу. isKlas() всегда возвращает true, поэтому это должно быть klas_fold.png ИЛИ klas_unfold.png. Но getTreeCellRendererComponent() выполняется только частично, потому что путь к файлу никогда не печатается, а значок не изменяется, это всегда значение по умолчанию!

Вот мой код:

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

Да, это внутренний класс.

Спасибо!

РЕДАКТИРОВАТЬ:

Я узнал, что это было ClassCastException, которое испортило вещи. Но это странно, потому что я инициализирую дерево так: new JTree({new TreeItem("params"), new TreeItem("params")});, Так что я должен быть в состоянии привести их обратно из объекта в TreeItem? (TreeItem - один из моих классов. Он расширяет DefaultMutableTreeNode).

3 ответа

Решение

Я решил это сам! я думал так Object value был TreeItem, который я вставил в JTree, но это было что-то еще. Я получил TreeItem, выполнив это (как в настройке ссылки на отображение дерева, предоставляемой mKorbel):

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

1) пытались ли вы уведомить TreeModel TreeModel.nodeChanged(node); это значение изменилось

2) поставить Icon(s) непосредственно в TreeModel, а не создавать заново TreeCellRenderer

3) JTree (JTable, JList а также JList от JComboBox) использовать ту же концепцию, что и Renderer для JTable

4) пожалуйста, прочитайте Настройка отображения дерева

5) примеры тут и тут

Я рад, что вы разобрались в части "попробовать-поймать". Чтобы решить эту проблему, убедитесь, что вы не предоставляете свой DefaultTreeModel ничего, кроме экземпляра TreeItem. Вы должны поставить эту строку System.out.println(value.getClass()) в вашем блоке улова.

Кроме того, вам следует рассмотреть возможность создания одного экземпляра ваших значков вместо создания нового каждый раз, когда узел дерева разворачивается или сворачивается.

Другие вопросы по тегам