Write a program to create two trees that display the same contents: world, continents, countries , and states, as shown in Figure 31.26. For the tree on the left, enable the user to choose a selection mode, specify whether it can be edited, add a new child under the first selected node, and remove all the selected nodes.
You can choose a selection mode from the selectionMode combo box. You can specify whether the left tree nodes can be edited from the editable check box.
When you click a button, if there are no nodes currently selected in the left tree, a message dialog box is displayed, as shown in Figure 31.27(a). When you click the Add a Child for Selected Node button, an input dialog box is displayed to prompt the user to enter a child name for the selected node, as shown in Figure 31.27(b). The new node becomes a child of the first selected node. When you click the Remove Selected Nodes button, all the selected nodes in the left tree are removed.
Listing 31.15 gives the program.
1 import java.awt.*; 2 import java.awt.event.*; 3 import javax.swing.*; 4 import javax.swing.tree.*; 5 6 public class ModifyTree extends JApplet { 7 // Create a combo box for choosing selection modes 8 private JComboBox jcboSelectionMode = new JComboBox( new String[]{ 9 "CONTIGUOUS_TREE_SELECTION" , "DISCONTIGUOUS_TREE_SELECTION" , 10 "SINGLE_TREE_SELECTION" }); 11 12 // Create a check box for specifying editable 13 private JCheckBox jchkEditable = new JCheckBox(); 14 15 // Create two buttons 16 private JButton jbtAdd = 17 new JButton( "Add a Child for Selected Node" ); 18 private JButton jbtRemove = new JButton( "Remove Selected Nodes" ); 19 20 // Declare two trees 21 private JTree jTree1, jTree2; 22 23 public ModifyTree() { 24 // Create the first tree 25 DefaultMutableTreeNode root, europe, northAmerica, us; 26 27 europe = new DefaultMutableTreeNode( "Europe" ); 28 europe.add( new DefaultMutableTreeNode( "UK" )); 29 europe.add( new DefaultMutableTreeNode( "Germany" )); 30 europe.add( new DefaultMutableTreeNode( "France" )); 31 europe.add( new DefaultMutableTreeNode( "Norway" )); 32 33 northAmerica = new DefaultMutableTreeNode( "North America" ); 34 us = new DefaultMutableTreeNode( "US" ); 35 us.add( new DefaultMutableTreeNode( "California" )); 36 us.add( new DefaultMutableTreeNode( "Texas" )); 37 us.add( new DefaultMutableTreeNode( "New York" )); 38 us.add( new DefaultMutableTreeNode( "Florida" )); 39 us.add( new DefaultMutableTreeNode( "Illinois" )); 40 northAmerica.add(us); 41 northAmerica.add( new DefaultMutableTreeNode( "Canada" )); 42 43 root = new DefaultMutableTreeNode( "World" ); 44 root.add(europe); 45 root.add(northAmerica); 46 47 jcboSelectionMode.setSelectedIndex( 1 ); 48 49 JPanel p1 = new JPanel(); 50 p1.add( new JLabel( "selectionMode" )); 51 p1.add(jcboSelectionMode); 52 p1.add( new JLabel( "editable" )); 53 p1.add(jchkEditable); 54 55 JPanel p2 = new JPanel( new GridLayout( 1 , 2 )); 56 p2.add( new JScrollPane(jTree1 = new JTree(root))); 57 p2.add( new JScrollPane(jTree2 = 58 new JTree( new DefaultTreeModel(root)))); // Same root as jTree1 59 60 JPanel p3 = new JPanel(); 61 p3.add(jbtAdd); 62 p3.add(jbtRemove); 63 64 add(p1, BorderLayout.NORTH); 65 add(p2, BorderLayout.CENTER); 66 add(p3, BorderLayout.SOUTH); 67 68 // Register listeners 69 jcboSelectionMode.addActionListener( new ActionListener() { 70 public void actionPerformed(ActionEvent e) { 71 if (jcboSelectionMode.getSelectedItem(). 72 equals( "CONTIGUOUS_TREE_SELECTION" )) 73 jTree1.getSelectionModel().setSelectionMode( 74 TreeSelectionModel.CONTIGUOUS_TREE_SELECTION); 75 else if (jcboSelectionMode.getSelectedItem(). 76 equals( "DISCONTIGUOUS_TREE_SELECTION" )) 77 jTree1.getSelectionModel().setSelectionMode( 78 TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION); 79 else 80 jTree1.getSelectionModel().setSelectionMode( 81 TreeSelectionModel.SINGLE_TREE_SELECTION); 82 } 83 }); 84 85 jchkEditable.addActionListener( new ActionListener() { 86 public void actionPerformed(ActionEvent e) { 87 jTree1.setEditable(jchkEditable.isSelected()); 88 } 89 }); 90 91 jbtAdd.addActionListener( new ActionListener() { 92 public void actionPerformed(ActionEvent e) { 93 DefaultMutableTreeNode parent = (DefaultMutableTreeNode) 94 jTree1.getLastSelectedPathComponent(); 95 96 if (parent == null ) { 97 JOptionPane.showMessageDialog( null , 98 "No node in the left tree is selected" ); 99 return ; 100 } 101 102 // Enter a new node 103 String nodeName = JOptionPane.showInputDialog( 104 null , "Enter a child node for " + parent, "Add a Child" , 105 JOptionPane.QUESTION_MESSAGE); 106 107 // Insert the new node as a child of treeNode 108 parent.add( new DefaultMutableTreeNode(nodeName)); 109 110 // Reload the model since a new tree node is added 111 ((DefaultTreeModel)(jTree1.getModel())).reload(); 112 ((DefaultTreeModel)(jTree2.getModel())).reload(); 113 } 114 }); 115 116 jbtRemove.addActionListener( new ActionListener() { 117 public void actionPerformed(ActionEvent e) { 118 // Get all selected paths 119 TreePath[] paths = jTree1.getSelectionPaths(); 120 121 if (paths == null ) { 122 JOptionPane.showMessageDialog( null , 123 "No node in the left tree is selected" ); 124 return ; 125 } 126 127 // Remove all selected nodes 128 for ( int i = ; i < paths.length; i++) { 129 DefaultMutableTreeNode node = (DefaultMutableTreeNode) 130 (paths[i].getLastPathComponent()); 131 132 if (node.isRoot()) { 133 JOptionPane.showMessageDialog( null , 134 "Cannot remove the root" ); 135 } 136 else 137 node.removeFromParent(); 138 } 139 140 // Reload the model since a new tree node is added 141 ((DefaultTreeModel)(jTree1.getModel())).reload(); 142 ((DefaultTreeModel)(jTree2.getModel())).reload(); 143 } 144 }); 145 } 146 } |
Two JTree objects ( jTree1 and jTree2 ) are created with the same root (lines 56 “58), but each has its own TreeSelectionModel . When you choose a selection mode in the combo box, the new selection mode is set in jTree1 's selection model (line 69 “83). The selection mode for jTree2 is not affected.
When the editable check box is checked or unchecked, the editable property in jTree1 is set accordingly . If editable is true, you can edit a node in the left tree.
When you click the Add a Child for Selected Node button, the first selected node is returned as parent (lines 93 “94). Suppose you selected Europe, UK, and US in this order, parent is Europe. If parent is null , no node is selected in the left tree (lines 96 “100). Otherwise, prompt the user to enter a new node from an input dialog box (lines 103 “105) and add this node as a child of parent (line 124). Since the tree has been modified, you need to invoke the reload() method to notify that the models for both trees have been changed (lines 111 “112). Otherwise, the new node may not be displayed in jTree1 and jTree2 .
When you click the Remove Selected Nodes button, all the tree paths for each selected node are obtained in paths (line 119). Suppose you selected Europe, UK, and US in this order, three tree paths are obtained. Each path starts from the root to a selected node. If no node is selected, paths is null . To delete a selected node is to delete the last node in each selected tree path (128 “138). The last node in a path is obtained using getLastPathComponent() . If the node is the root, it cannot be removed (lines 132 “134). The removeFromParent() method removes a node (line 137).