javajtree

Create Jtree dynamically


I'm struggling with creating a Jtree dynamically. What I have in mind is to store the string for nodes in properties file and loop through them, adding the Default mutable tree nodes to the root node. I prefer Properties, because I'd like to be able to change them from the app itself or by editing the *.properies file manually.

I want to create a model with parents and children (sometimes two children). I've managed to create nodes, but can't figure out how can it be done, so there would be parents and children, so I would set which nodes would be children to specific parent nodes. That is what I have for now, plus a properties file with couple of keys and properties, in which I store the node strings:

DefaultMutableTreeNode allnodes = new DefaultMutableTreeNode("", true);
            DefaultMutableTreeNode elements = new DefaultMutableTreeNode("Elements", true);

            Set<String> keys = Prop1.stringPropertyNames();
            for (String key : keys) {
                DefaultMutableTreeNode node = new DefaultMutableTreeNode(Prop1.getProperty(key), false);
                elements.add(node);
            }
            allnodes.add(elements);

            tree1 = new JTree(allnodes);

The problem is that this can only produce children or parent, based on what boolean I put creating it with:

DefaultMutableTreeNode node = new DefaultMutableTreeNode(Prop1.getProperty(key), false);

Can anyone tell me if that's possible and if it is, how can I accomplish it. Also I've read similar questions and answers everywhere and I couldn't find something that fits my needs. I would greatly appreciate any help I could get. Peter


Solution

  • The problem is, you need some way to describe your hierarchy. Using a flat hierarchy (like a String path) will be very hard to parse, as you will need some way to look up previously created parent nodes and create the paths when they don't exist.

    Better to use something like XML or JSON, which can more easily describe hierarchy related data

    The following is an, overly simple, example of one way of approaching this, pay attention to the populate(DefaultMutableTreeNode parent, Item item) method

    enter image description here

    Json...

    [
       {
          "name":"Bowle",
          "contents":[
             {
                "name":"Apple",
                "contents":[
                   
                ]
             },
             {
                "name":"Pear",
                "contents":[
                   
                ]
             },
             {
                "name":"Orange",
                "contents":[
                   
                ]
             }
          ]
       },
       {
          "name":"Freezer",
          "contents":[
             {
                "name":"Top draw",
                "contents":[
                   {
                      "name":"Chicken",
                      "contents":[
                         
                      ]
                   },
                   {
                      "name":"Steak",
                      "contents":[
                         
                      ]
                   },
                   {
                      "name":"Fish",
                      "contents":[
                         
                      ]
                   }
                ]
             },
             {
                "name":"Bottom draw",
                "contents":[
                   {
                      "name":"Peas",
                      "contents":[
                         
                      ]
                   },
                   {
                      "name":"Chips",
                      "contents":[
                         
                      ]
                   },
                   {
                      "name":"Ice cream",
                      "contents":[
                         
                      ]
                   }
                ]
             }
          ]
       }
    ]
    

    Source...

    import com.google.gson.Gson;
    import java.awt.BorderLayout;
    import java.awt.Component;
    import java.awt.EventQueue;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.util.ArrayList;
    import java.util.List;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    import javax.swing.JTree;
    import javax.swing.tree.DefaultMutableTreeNode;
    import javax.swing.tree.DefaultTreeCellRenderer;
    import javax.swing.tree.DefaultTreeModel;
    import javax.swing.tree.TreeModel;
    
    public class Main {
    
        public static void main(String[] args) {
            new Main();
        }
    
        public Main() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try (InputStreamReader reader = new InputStreamReader(getClass().getResourceAsStream("/resources/ImportantStuff.json"))) {
                        Gson gson = new Gson();
                        Item[] items = gson.fromJson(reader, Item[].class);
    
                        DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode("My stuff");
                        DefaultTreeModel model = new DefaultTreeModel(rootNode);
    
                        for (Item item : items) {
                            populate(rootNode, item);
                        }
    
                        JFrame frame = new JFrame();
                        frame.add(new MainPane(model));
                        frame.pack();
                        frame.setLocationRelativeTo(null);
                        frame.setVisible(true);
    
                    } catch (IOException ex) {
                        ex.printStackTrace();
                    }
                }
            });
        }
    
        public class MainPane extends JPanel {
    
            public MainPane(TreeModel model) {
                setLayout(new BorderLayout());
                JTree tree = new JTree(model);
                tree.setCellRenderer(new ItemTreeCellRenderer());
                tree.setShowsRootHandles(true);
                add(new JScrollPane(tree));
            }
    
        }
    
        public class ItemTreeCellRenderer 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);
                if (value instanceof DefaultMutableTreeNode) {
                    DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
                    Object userObject = node.getUserObject();
                    if (userObject instanceof Item) {
                        Item item = (Item) userObject;
                        setText(item.getName());
                    }
                }
                return this;
            }
    
        }
    
        protected void populate(DefaultMutableTreeNode parent, Item item) {
            DefaultMutableTreeNode node = new DefaultMutableTreeNode(item);
            parent.add(node);
    
            for (Item child : item.getContents()) {
                populate(node, child);
            }
        }
    
        public class Item {
            private String name;
            private List<Item> contents;
    
            public Item(String name) {
                this.name = name;
                this.contents = new ArrayList<>(8);
            }
    
            public String getName() {
                return name;
            }
    
            public List<Item> getContents() {
                return contents;
            }
        }
    }