Jtree Renderer设置自定义图标不起作用

时间:2013-04-14 19:54:12

标签: java swing jtree renderer

我正在尝试解析以下XML文件,并使用自定义图标创建基于它的JTree。

<OBJECTS>
    <WINDOW NAME = "WINDOW 01" URL = "URL 01">
        <PAGE NAME = "PAGE 01" URL = "PAGE URL 01">
        </PAGE>
    </WINDOW>
</OBJECTS>

用户定义的节点类如下所示:

public class DataNode extends DefaultMutableTreeNode {    
    private static final long serialVersionUID = 1L;
    public String ObjectType, ObjectName, URL, ElementType;
    public DefaultMutableTreeNode node;

    public DataNode(DefaultMutableTreeNode node, Element element) {
        this.node = node;
        this.ObjectType = element.getTagName();
        this.ObjectName = element.getAttribute("NAME");
        this.URL = element.getAttribute("URL");
        this.ElementType = element.getAttribute("TYPE");
    }

    public DataNode(Element element) {
        this.node = new DefaultMutableTreeNode("OBJECT");
        this.ObjectType = element.getTagName();
        this.ObjectName = "Object List";
        this.URL = "";
        this.ElementType = "";
    }

    @Override
    public String toString() {
        return this.ObjectName;
    }
}

这是主要课程:

public class MyOwn {
    private JFrame contentsFrame;

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    MyOwn window = new MyOwn();
                    window.contentsFrame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    public MyOwn() {
        contentsFrame = new JFrame();
        contentsFrame.setTitle("My JTree");
        contentsFrame.setBounds(100, 100, 549, 738);
        contentsFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JTree objectListTree = new JTree(convertXMLtoTree("G:/Collection.xml"));
        objectListTree.setAlignmentY(Component.TOP_ALIGNMENT);
        objectListTree.setAlignmentX(Component.LEFT_ALIGNMENT);

        contentsFrame.getContentPane().add(new JScrollPane(objectListTree));
    }

    private DefaultMutableTreeNode convertXMLtoTree(String Path) {
        NodeList nWindow, nPage;
        DefaultMutableTreeNode dRoot, dWindow, dPage;
        DataNode xRoot, xWindow, xPage;

        try {
            File fXmlFile = new File(Path);
            DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
            Document doc = dBuilder.parse(fXmlFile);

            doc.getDocumentElement().normalize();
            xRoot = new DataNode(doc.getDocumentElement());
            dRoot = new DefaultMutableTreeNode(xRoot);
            nWindow = doc.getDocumentElement().getElementsByTagName("WINDOW");

            for (int i = 0; i < nWindow.getLength(); i++) {
                dWindow = new DefaultMutableTreeNode(((Element)(nWindow.item(i))).getAttribute("NAME"));
                xWindow = new DataNode(dWindow, (Element)(nWindow.item(i)));
                dRoot.add(xWindow);
                nPage = ((Element)(nWindow.item(i))).getElementsByTagName("PAGE");
                for (int j = 0; j < nPage.getLength(); j++) {
                    dPage = new DefaultMutableTreeNode(((Element)(nPage.item(j))).getAttribute("NAME"));
                    xPage = new DataNode(dPage, (Element)(nPage.item(j)));
                    xWindow.add(xPage);
                }
            }
            return dRoot;
        } catch (Exception e) {
            return null;
        }
    }
}

渲染器类如下所示:(突出显示NullPointerException的行)

class MyRenderer extends DefaultTreeCellRenderer {

    private static final long serialVersionUID = 1L;

    public MyRenderer() { }

    public String toString() {
        return "NODE NAME";
    }

    public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus)
    {
        ImageIcon ObjectsIcon = createImageIcon("images/Element.JPG");
        ImageIcon WindowIcon = createImageIcon("images/fig7.jpg");
        ImageIcon PageIcon = createImageIcon("images/message_icon.gif");
        ImageIcon UnknownIcon = createImageIcon("images/phone_icon.gif");

        super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);

        switch (ObjectType(value)) {
            case 1: setIcon(ObjectsIcon);
                    break;
            case 2: setIcon(WindowIcon);
                    break;
            case 3: setIcon(PageIcon);
                    break;
            case 0: setIcon(UnknownIcon);
                    break;
        }

        return this;
    }

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

    private int ObjectType(Object value) {
        DefaultMutableTreeNode node = (DefaultMutableTreeNode)value;
        DataNode nodeInfo = (DataNode) node.getUserObject(); //This is where the NullPointerException occurs
        String title = nodeInfo.ObjectType;

        if (title.equalsIgnoreCase("OBJECT"))
            return 1;
        else if (title.equalsIgnoreCase("WINDOW"))
            return 2;
        else if (title.equalsIgnoreCase("PAGE"))
            return 3;
        else
            return 0;
    }
}

请告诉我为什么nodeInfo对象为null?谢谢你的帮助...

1 个答案:

答案 0 :(得分:2)

节点对象为null,因为您没有为自定义DefaultMutableTreeNode DataNode设置用户对象。鉴于您希望匹配可以使用的节点文本:

public DataNode(DefaultMutableTreeNode node, Element element) {
   super(element.getTagName());
       ...
}

然后,在MyRenderer

if (value instanceof DataNode) { // added check for class type
   String title = (String) node.getUserObject();
   ...

另外,在DefaultMutableTreeNode中使用DataNode作为类成员变量是不必要的。它已经 DefaultMutableTreeNode,并且可以使用超类中的继承方法处理任何可能的节点操作。