Monkeys and Koalas are not the only things that climb trees, Programmers do too! But our trees are a bit more virtual. In Java (and many other languages) there is a control known as a Tree or Treeview. It is used to create a hierarchy display much like you see in Windows Explorer in the left hand pane. You can see nodes and how they relate to one another much like files belong in a folder and folders can belong in other folders. These controls are great for condensing content down into compact lists. It also allows the user to expand a node to get at its sub items or “children” as they are often called. How do we go about creating a basic JTree in Java and populating it with some information? On top of that, how do we know what was selected by the user? We tackle these puzzling questions in this entry of the Programming Underground!
The best way to understand a JTree or any Treeview control is to look at it from the point of a single node. A node can be an object like a folder or a file or even a simple string and can contain other nodes. Add a node to another node and you can say that this sub node is a “child” of the “parent” node. Understanding this basic concept and its analogy to a family (two nodes under the same node are sibling nodes) can get you really far in learning about these types of tree structures.
To help illustrate the concept, we have created a very basic and very VERBOSE example below to show you how each node can be added to a JTree control in Java and how we might go about adding nodes to other nodes and adding nodes to those subnodes. Through each step we build on the previous nodes to form a hierarchy that we can show with a screenshot.
After the demo code below (which btw is fully commented as usual) we will talk about detecting a selected node and how we might glean some information from it. After all, what good is it to list nodes, allow the user to select one, and not be able to use information about it?
ExampleTree.java
import javax.swing.*; // Needed for accessing various JTree components and events listening code import javax.swing.tree.*; import javax.swing.event.TreeSelectionListener; import javax.swing.event.TreeSelectionEvent; // Lets create a class which extends from a standard JFrame control and listens for when the user selects an item from our JTree public class ExampleTree extends JFrame implements TreeSelectionListener { // Here we create our JTree as a private member control private JTree tree; // Main will create an instance of our class ExampleTree and set its properties including size and to show it. // Notice it does nothing else. When we create the example of ExampleTree, it will call its constructor below. public static void main(String args[]) { ExampleTree frame = new ExampleTree(); frame.setTitle("Example of JTree"); frame.setSize(300,300); frame.setDefaultCloseOperation(EXIT_ON_CLOSE); frame.setVisible(true); } // This is our constructor for our class. It sets up the tree with its nodes upon creation of the class // It then adds the branches and their leaves to the JTree, then lastly adds the JTree to the JFrame. // Take notice of the hierarchy here... Leaves to branches, branches to root, root to JTree, JTree to ScrollPane, ScrollPane to // to ExampleTree which is an instance of of a JFrame control. public ExampleTree() { // Here we create a top level root node. We give it the text "Root Node" DefaultMutableTreeNode top = new DefaultMutableTreeNode("Root Node"); // Give this node to JTree when we create it. Now our Tree has one node. tree = new JTree(top); // While we are at it, configure the control to allow only one selection at a time and attach our listener to it // Listener is explained below. tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); tree.addTreeSelectionListener(this); // Attach the JTree to our scrollpane so it will scroll when the list becomes longer. JScrollPane treeView = new JScrollPane(tree); // Ok, so we have one root node, now we create three branches. Create a node for each branch. DefaultMutableTreeNode branch1 = new DefaultMutableTreeNode("Branch Node 1"); DefaultMutableTreeNode branch2 = new DefaultMutableTreeNode("Branch Node 2"); DefaultMutableTreeNode branch3 = new DefaultMutableTreeNode("Branch Node 3"); // Add the branches to our root node in the JTree. top.add(branch1); top.add(branch2); top.add(branch3); // Create some Leaf nodes. DefaultMutableTreeNode leaf1 = new DefaultMutableTreeNode("leaf 1"); DefaultMutableTreeNode leaf2 = new DefaultMutableTreeNode("leaf 2"); DefaultMutableTreeNode leaf3 = new DefaultMutableTreeNode("leaf 3"); DefaultMutableTreeNode leaf4 = new DefaultMutableTreeNode("leaf 4"); DefaultMutableTreeNode leaf5 = new DefaultMutableTreeNode("leaf 5"); DefaultMutableTreeNode leaf6 = new DefaultMutableTreeNode("leaf 6"); // Add first to leaves to branch 1 branch1.add(leaf1); branch1.add(leaf2); // One leaf on branch 2 branch2.add(leaf3); // Last three on branch 3 branch3.add(leaf4); branch3.add(leaf5); branch3.add(leaf6); // Now add the ScrollPane (which contains the JTree) to the screen. add(treeView); } // This is our TreeSelectionListener. It is attached to our JTree earlier. // It is called any time one of the nodes are clicked on or selected. public void valueChanged(TreeSelectionEvent e) { // First thing is first, get the node that was selected and cast it to a DefaultMutableTreeNode. // JTree sees its nodes as objects, it doesn't know they are tree nodes in this case. DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent(); if (node == null) return; // Now ask the node, are you a leaf node? A node with no children. // If so, show a message to the user saying it is a leaf. Otherwise it is not a leaf node. if (node.isLeaf()) { JOptionPane.showMessageDialog(null,"This is a leaf node"); } else { JOptionPane.showMessageDialog(null,"This is not a leaf node"); } } }
The code is a basic Java Swing application. We start by creating a class which derives from JFrame and implements an action listener called “TreeSelectionListener”. This listener which will listen for the user selecting a node in the tree. In the main method we create an instance of our class and set its title, size, and the call to show it to the user. But before all this takes place, when we create the instance of our class, java will call the ExampleTree constructor which will setup our JTree.
In the ExampleTree constructor we do most of the work to setup our JTree. We create our root node (the top most node of the entire tree) and call it “top”. This node is of type DefaultMutableTreeNode which offers a lot of methods for handling the node including its relationship to other nodes. With it you can determine if a node has children etc.
We give this top level node to the JTree constructor to create a JTree control called “tree”. So our tree now has one single root node in it with the title “Root node”. Fantastic! We are already half way there. At this point in the game we will tell the tree control to use a selection mode of selecting only a single node at a time as opposed to multiple selections. We then attach our listener event (defined towards the end). After we do this our JTree can now respond to user events. We also take the step of adding it to a scrollpane object so that the tree will create scrolling abilities when the list gets really long. That is all for configuring the actual JTree control. The rest of the code will be dedicated to building the hierarchy of nodes.
The second half of the game is to create more nodes and simply add them to our root node. We call these nodes branches since they will be off the root node but will contain other nodes of their own which will be leaf nodes. See the relation? Root -> Branch -> Leaf? This can correspond to “Grandparent -> Parent -> Child” and to keep this terminology straight, think of the tree as a family tree.
After we create the branch nodes and add them to the root, we go about creating 6 leaf nodes. We add the first 2 to our first branch, the third leaf to the second branch, and the last 3 to branch 3.
Lastly we add the tree to the JFrame and then the stuff in main will finish firing and show the application to the user. The product is the following screenshot…
Now that we have added the nodes, it is time to handle the user when they click one of the nodes. In our example we determine if the node they selected was a leaf node (has no children) or not. This is accomplished using the valuechanged method which is part of the TreeSelectionListener. When a user clicks a node in the JTree, it knows to call the listener (which we attached to JTree earlier remember?) and thus calls the valuechanged method.
In this function we get the node the user selected, cast it to a DefaultMutableTreeNode (since the JTree treats its nodes as objects) so that we can get access to the node’s methods. Here we simply use the “isLeaf()” method to determine if the node is a leaf node (having no children). If it is, we simply display a message saying it is a leaf node. Otherwise we tell the user it is not a leaf node.
That is all there is to it to creating a basic JTree control. Explore the methods of DefaultMutableTreeNode and you will see that there are plenty of methods there for getting information about the node including its position in the list, if it has children, and more. Run through the in-code comments slowly and build it up as you go. This will help you better understand how everything is put together.
I hope this basic run through of the JTree control will help you in getting started using this control. If you have any further questions, be sure to ask the regulars in the Java forum, and if I see it I will respond personally.
Enjoy and thanks again for reading! 🙂