Jtree Renderer для установки пользовательских значков не работает

Я пытаюсь проанализировать приведенный ниже файл XML и создать на его основе JTree с настраиваемыми значками.

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

Класс User Defined Node приведен ниже:

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 ?? Спасибо за вашу помощь...


person Vel Ganesh    schedule 14.04.2013    source источник
comment
Либо отладьте код, чтобы проверить состояние узла, либо введите System.out.println.   -  person MadProgrammer    schedule 15.04.2013
comment
Чтобы быстрее получить помощь, опубликуйте SSCCE.   -  person Andrew Thompson    schedule 15.04.2013


Ответы (1)


Объект узла — 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, и любые возможные операции с узлами можно обрабатывать с помощью методов, унаследованных от суперкласса.

person Reimeus    schedule 14.04.2013