Introduction to Java Programming-Comprehensive Version (6th Edition)
31.10. TreeNode , MutableTreeNode , and DefaultMutableTreeNode
While TreeModel represents the entire tree, TreeNode stores a single node of the tree. MutableTreeNode defines a subinterface of TreeNode with additional methods for changing the content of the node, for inserting and removing a child node, for setting a new parent, and for removing the node itself.
DefaultMutableTreeNode is a concrete implementation of MutableTreeNode that maintains a list of children in a vector and provides the operations for creating nodes, for examining and modifying a node's parent and children, and also for examining the tree to which the node belongs. Normally, you should use DefaultMutableTreeNode to create a tree node. Figure 31.21 shows TreeNode , MutableTreeNode , and DefaultMutableTreeNode .
Figure 31.21. TreeNode represents a node.
(This item is displayed on page 1076 in the print version)
Note
| In graph theory, depth-first traversal is defined the same as preorder traversal, but in the depthFirstEnumeration() method in DefaultMutableTreeNode , it is the same as postorder traversal. |
Note
| You can create a JTree from a root using new JTree(TreeNode) or from a model using new JTree(TreeModel). To create a tree model, you first create an instance of TreeNode to represent the root of the tree, and then create an instance of DefaultTreeModel fitted with the root. |
Listing 31.13 gives an example that creates two trees to display world, continents, countries , and states. The two trees share the same nodes and thus display identical contents. The program also displays the properties of the tree in a text area, as shown in Figure 31.22.
Figure 31.22. The two trees have the same data because their roots are the same.
(This item is displayed on page 1077 in the print version)
Listing 31.13. TreeNodeDemo.java
(This item is displayed on pages 1074 - 1075 in the print version)
1 import java.awt.*; 2 import javax.swing.*; 3 import javax.swing.tree.*; 4 import java.util.*; 5 6 public class TreeNodeDemo extends JApplet { 7 public TreeNodeDemo() { 8 // Create the first tree 9 DefaultMutableTreeNode root, europe, northAmerica, us; 10 11 europe = new DefaultMutableTreeNode( "Europe" ); 12 europe.add( new DefaultMutableTreeNode( "UK" )); 13 europe.add( new DefaultMutableTreeNode( "Germany" )); 14 europe.add( new DefaultMutableTreeNode( "France" )); 15 europe.add( new DefaultMutableTreeNode( "Norway" )); 16 17 northAmerica = new DefaultMutableTreeNode( "North America" ); 18 us = new DefaultMutableTreeNode( "US" ); 19 us.add( new DefaultMutableTreeNode( "California" )); 20 us.add( new DefaultMutableTreeNode( "Texas" )); 21 us.add( new DefaultMutableTreeNode( "New York" )); 22 us.add( new DefaultMutableTreeNode( "Florida" )); 23 us.add( new DefaultMutableTreeNode( "Illinois" )); 24 northAmerica.add(us); 25 northAmerica.add( new DefaultMutableTreeNode( "Canada" )); 26 27 root = new DefaultMutableTreeNode( "World" ); 28 root.add(europe); 29 root.add(northAmerica); 30 31 JPanel panel = new JPanel(); 32 panel.setLayout( new GridLayout( 1 , 2 )); 33 panel.add( new JScrollPane( new JTree(root)) ); 34 panel.add( new JScrollPane( new JTree( new DefaultTreeModel(root))) ); 35 36 JTextArea jtaMessage = new JTextArea(); 37 jtaMessage.setWrapStyleWord( true ); 38 jtaMessage.setLineWrap( true ); 39 add( new JSplitPane(JSplitPane.VERTICAL_SPLIT, 40 panel, new JScrollPane(jtaMessage)), BorderLayout.CENTER); 41 42 // Get tree information 43 jtaMessage.append( "Depth of the node US is " + us.getDepth()); 44 jtaMessage.append( "\nLevel of the node US is " + us.getLevel()); 45 jtaMessage.append( "\nFirst child of the root is " + 46 root.getFirstChild()); 47 jtaMessage.append( "\nFirst leaf of the root is " + 48 root.getFirstLeaf()); 49 jtaMessage.append( "\nNumber of the children of the root is " + 50 root.getChildCount()); 51 jtaMessage.append( "\nNumber of leaves in the tree is " + 52 root.getLeafCount()); 53 String breadthFirstSearchResult = "" ; 54 55 // Breadth-first traversal 56 Enumeration bf = root.breadthFirstEnumeration() ; 57 while (bf.hasMoreElements()) 58 breadthFirstSearchResult += bf.nextElement().toString() + " " ; 59 jtaMessage.append( "\nBreath-first traversal from the root is " 60 + breadthFirstSearchResult); 61 } 62 }
|
You can create a JTree using a TreeNode root (line 33) or a TreeModel (line 34), whichever is convenient . A TreeModel is actually created using a TreeNode root (line 34). The two trees have the same contents because the root is the same. However, it is important to note that the two JTree objects are different, and so are their TreeModel objects, although both trees have the same root.
A tree is created by adding the nodes to the tree (lines 9 “29). Each node is created using the DefaultMutableTreeNode class. This class provides many methods to manipulate the tree (e.g., adding a child, removing a child) and obtaining information about the tree (e.g., level, depth, number of children, number of leaves, traversals). Some examples of using these methods are given in lines 43 “60.
As shown in this example, often you don't have to directly use TreeModel . Using DefaultMutableTreeNode is sufficient, since the tree data is stored in DefaultMutableTreeNode , and DefaultMutableTreeNode contains all the methods for modifying the tree and obtaining tree information.