Search code examples
javaswingjtreeevent-listenertreemodel

Adding a Swing tree selection listener with custom tree model


I am studing java now, and one of my apps is simple Swing file hierarchy viewer, that uses JTree widget.My question is how can i add a Jtree mouse selection event listener(for example logging a node text value to console) in case when i implemented a TreeModel this way (example from the book "Java Foundation Classes in a Nutshell" ):

    public class FileTreeDemo {
    public static void main(String[] args) {
        File root;
        if (args.length > 0)
            root = new File(args[0]);
        else
            root = new File(System.getProperty("user.home"));

                FileTreeModel model = new FileTreeModel(root);

        MyJtree tree = new MyJtree();
        tree.setModel(model);

        JScrollPane scrollpane = new JScrollPane(tree);

        JFrame frame = new JFrame("FileTreeDemo");
        frame.getContentPane().add(scrollpane, "Center");
        frame.setSize(400, 600);
        frame.setVisible(true);
    }
}

class FileTreeModel implements TreeModel {
    protected File root;

    public FileTreeModel(File root) {
        this.root = root;
    }

    public Object getRoot() {
        return root;
    }

    public boolean isLeaf(Object node) {
        return ((File) node).isFile();
    }

    public int getChildCount(Object parent) {
        String[] children = ((File) parent).list();
        if (children == null)
            return 0;
        return children.length;
    }

    public Object getChild(Object parent, int index) {
        String[] children = ((File) parent).list();
        if ((children == null) || (index >= children.length))
            return null;
        return new File((File) parent, children[index]);
    }

    public int getIndexOfChild(Object parent, Object child) {
        String[] children = ((File) parent).list();
        if (children == null)
            return -1;
        String childname = ((File) child).getName();
        for (int i = 0; i < children.length; i++) {
            if (childname.equals(children[i]))
                return i;
        }
        return -1;
    }

    public void valueForPathChanged(TreePath path, Object newvalue) {
    }

    public void addTreeModelListener(TreeModelListener l) {
    }

    public void removeTreeModelListener(TreeModelListener l) {
    }
}

Here i am trying to extend JTree class by MyJtree and add AddTreeSelectionListener

public class MyJtree extends JTree {
    public MyJtree() {
        super();
        this.addTreeSelectionListener(new TreeSelectionListener() {
            public void valueChanged(TreeSelectionEvent e) {
                DefaultMutableTreeNode node = (DefaultMutableTreeNode) e
                        .getPath().getLastPathComponent();
                System.out.println("You selected " + node);
            }
        });
    }
}

But then i click on JTree item, i get this :

Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: java.io.File cannot be cast to javax.swing.tree.DefaultMutableTreeNode

So, how should I fix that ?


Solution

  • Since your model contains File objects, e.getPath().getLastPathComponent() returns File object (Just the object that your model returns). Additionally to avoid ClassCastException you may want to check if the returned Object exact class you expect.

    Object object = e.getPath().getLastPathComponent(); 
    if (object instanceof File){ 
        File file = (File) object; 
    }