【问题标题】:Strange DefaultTreeCellRenderer behaviour, only partially executing getTreeCellRendererComponent()奇怪的 DefaultTreeCellRenderer 行为,仅部分执行 getTreeCellRendererComponent()
【发布时间】:2012-05-17 09:11:15
【问题描述】:

我创建了一个 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")});。所以我应该能够将它们从 Object 转换回 TreeItem? (TreeItem 是我的类之一。它扩展了 DefaultMutableTreeNode)。

【问题讨论】:

  • 1) 为了尽快获得更好的帮助,请发帖 SSCCE。 2) 构造DefaultTreeCellRenderer时加载和缓存图片。
  • 好主意,我自己永远不会想出SSCCE

标签: java swing jtree treecellrenderer


【解决方案1】:

1) 您是否尝试通知 TreeModel TreeModel.nodeChanged(node); 该值已更改

2) 将Icon(s) 直接放到TreeModel 中,而不是在TreeCellRenderer 里面重新创建

3) JTreeJTableJListJList 来自JComboBox)分享相同的concept as Renderer for JTable

4) 请阅读Customizing a Tree's Display

5) 示例herehere

【讨论】:

    【解决方案2】:

    我自己解决了!我以为Object value 是我放在JTree 中的TreeItem,但它是别的东西。我通过这样做得到了 TreeItem(就像在 mKorbel 提供的自定义树的显示链接中一样):

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

    【讨论】:

      【解决方案3】:

      很高兴您了解了 try-catch 部分。要解决此问题,请确保您没有提供除 TreeItem 实例之外的任何 DefaultTreeModel。您应该将此行 System.out.println(value.getClass()) 放在您的 catch 块中。

      此外,您应该考虑创建一个图标实例,而不是每次展开或折叠树节点时都创建一个新实例。

      【讨论】:

      • System.out.println(value.getClass()); 让我输出:class javax.swing.JTree$DynamicUtilTreeNode
      猜你喜欢
      • 1970-01-01
      • 2011-12-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多