Search code examples
javaswingjtree

Making a JTree leaf appear as an empty directory and not a file


I'm learning my way around Java JTree's but I have this little problem I can't figure out. Using a tutorial I found on Oracle's site, I've mimicked a tree structure they demonstrate. The problem is, I want the Folder "websites" to be an empty folder, but JTree is displaying it as though it is a file. How can I tell the JTree that "websites" is in fact an empty folder?

UPDATE

I've started working on a simple 'contact manager'. What I want to do basically it make the name look like folders (since I want to add info to each of them), but without adding stuff. i.e. Some might not have any info in them, but I would still like them to look like folders.

enter image description here

Code for the Browser class:

import java.awt.Component;
import java.io.File;
import java.util.Iterator;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;


public class Browser extends JFrame implements javax.swing.tree.TreeModel {


    private JTree tree;
    ManagerOfContacts mngrOfContacts;

    public Browser() {

        //Generates the ManagerOfContacts and associated Contacts
        Driver driver = new Driver();
        mngrOfContacts = driver.getManagerOfContacts();
        //---------------------------\\


        DefaultMutableTreeNode contacts = new DefaultMutableTreeNode("Contacts");
        createNodes(contacts);
        tree = new JTree(contacts);

        JScrollPane treeView = new JScrollPane(tree);

        add(treeView);

        setSize(400,400);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setVisible(true);
    }

    public void createNodes(DefaultMutableTreeNode top){
        DefaultMutableTreeNode contactName;

        Iterator<Contact> contactItr = mngrOfContacts.getIterator();
        while(contactItr.hasNext()){
            contactName = new DefaultMutableTreeNode(contactItr.next());
            top.add(contactName);
        }
    }

    public static void main(String[] args) {
        Browser browsr = new Browser();
    }

}

Solution

  • This is how you create your own TreeCellRenderer which tells your JTree whatever you want. Since you are using a default tree model with DefaultMutableTreeNode as nodes you have to extract their user object and decide what to paint based on that. Note that the default renderer is just an extended JLabel, which is why you can use setIcon(...), setText(...), etc. inside it.

    The reason why your leaf nodes are painted with file icons is probably that the default renderer chooses the icon based on DefaultMutableTreeNode.getAllowsChildren() similarily to how I use Contact.isSomeProperty().

    import java.awt.Component;
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;
    import javax.swing.JFrame;
    import javax.swing.JScrollPane;
    import javax.swing.JTree;
    import javax.swing.SwingUtilities;
    import javax.swing.UIManager;
    import javax.swing.tree.DefaultMutableTreeNode;
    import javax.swing.tree.DefaultTreeCellRenderer;
    
    
    public class Browser extends JFrame {
    
    
        private JTree tree;
        //ManagerOfContacts mngrOfContacts;
    
        public Browser() {
    
            //Generates the ManagerOfContacts and associated Contacts
            //Driver driver = new Driver();
            //mngrOfContacts = driver.getManagerOfContacts();
            //---------------------------\\
    
    
            DefaultMutableTreeNode contacts = new DefaultMutableTreeNode("Contacts");
            createNodes(contacts);
            tree = new JTree(contacts);
    
            // use your own renderer (!)
            tree.setCellRenderer(new MyTreeCellRenderer());
    
            JScrollPane treeView = new JScrollPane(tree);
    
            add(treeView);
    
            setSize(400,400);
            setDefaultCloseOperation(EXIT_ON_CLOSE);
            setVisible(true);
        }
    
        public final void createNodes(DefaultMutableTreeNode top){
            DefaultMutableTreeNode contactName;
    
            // dummies
            List<Contact> contacts = new ArrayList<Contact>();
            contacts.add(new Contact("Me", true));
            contacts.add(new Contact("You"));
    
            Iterator<Contact> contactItr = contacts.iterator();
            while(contactItr.hasNext()){
                contactName = new DefaultMutableTreeNode(contactItr.next());
                top.add(contactName);
            }
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    Browser browsr = new Browser();
                }
            });
    
        }
    
        // dummy
        private static class Contact {
    
            private boolean someProperty;
            private String name;
    
            public Contact(String name) {
                this(name, false);
            }
    
            public Contact(String name, boolean property) {
                this.someProperty = property;
                this.name = name;
            }
    
            public boolean isSomeProperty() {
                return someProperty;
            }
    
            public String getName() {
                return name;
            }
    
            @Override
            public String toString() {
                return name;
            }
        }
    
        // this is what you want
        private static class MyTreeCellRenderer extends DefaultTreeCellRenderer {
    
            @Override
            public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) {
                super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
    
                // decide what icons you want by examining the node
                if (value instanceof DefaultMutableTreeNode) {
                    DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
                    if (node.getUserObject() instanceof String) {
                        // your root node, since you just put a String as a user obj                    
                        setIcon(UIManager.getIcon("FileView.computerIcon"));
                    } else if (node.getUserObject() instanceof Contact) {
                        // decide based on some property of your Contact obj
                        Contact contact = (Contact)  node.getUserObject();
                        if (contact.isSomeProperty()) {
                            setIcon(UIManager.getIcon("FileView.hardDriveIcon"));
                        } else {
                            setIcon(UIManager.getIcon("FileChooser.homeFolderIcon"));
                        }
                    }
                }
    
                return this;
            }
    
        }
    }
    

    This should get you started. You should read more about this in a JTree tutorial.