- The Tree Control
- Tree Appearance
- The TreeNode Interface
- The MutableTreeNode Interface
- The DefaultMutableTreeNode Class
- The TreePath Class
- What is a Leaf?
- Tree Expansion and Traversal
- Expanding and Collapsing Nodes under Program Control
- Tree Expansion Events
- Making Nodes Visible
- Controlling Node Expansion and Collapse
- Tree Model Events
- Implementation Plan for the File System Control
- File System Tree Control Implementation
- Using the File System Tree Control
- Custom Tree Rendering and Editing
- Customizing the Default Tree Cell Renderer
- ToolTips and Renderers
- Custom Cell Editors
- Controlling Which Nodes Can Be Edited
- Controlling Editability by Subclassing JTree
- Programmatic Control of Editors
- Editing Trees with Custom User Objects
- The valueForPathChanged Method
- The Tree Implementation
- The Cell Editor
- The Cell Renderer
- Summary
Tree Expansion Events
Every time a node in the tree is expanded or collapsed, a TreeExpansion-Event is generated. You can receive these events by registering a TreeEx-pansionListener on the JTree itself. The TreeExpansionListener interface has only two methods:
public void treeExpanded(TreeExpansionEvent event) public void treeCollapsed(TreeExpansionEvent event)
The TreeExpansionEvent contains a source field that corresponds to the JTree itself and a TreePath that represents the node was expanded or collapsed. You can obtain the source of the events using the usual get-Source method and the path using getPath:
public TreePath getPath();
Sometimes, expanding a path can generate more than one event, because it may be necessary to expand other nodes to make the target node visible. To see the events that are generated when this happens, we created a modified version of TreeExample1 that registers a TreeExpansionListener and prints the events that it receives. Here is the snippet of code that was added to implement the listener:
t.addTreeExpansionListener(new TreeExpansionListener() { public void treeExpanded(TreeExpansionEvent evt) { System.out.println("Expansion event, path " + evt.getPath()); } public void treeCollapsed(TreeExpansionEvent evt) { System.out.println("Collapse event, path " + evt.getPath()); } });
You can run the modified version of the program using the command:
javac JFCBook.Chapter10.TreeExample3
The code was also changed so that the tree starts with only the root visible by adding the line:
t.collapseRow(0);
If you expand and collapse nodes in the tree, you'll see the events that are generated displayed in the window from which you started the program. Notice that there is one event generated each time you expand or collapse a node. This remains true even if you open the whole tree and then collapse it by double-clicking on the root node. The event that you get contains a Tree-Path for the root: You don't get events for all of the other nodes that disappeared. This is actually reasonable, because if you expand the root again, you'll find that the tree returns to its fully expanded statein other words, the other nodes didn't actually collapse. As well as adding a listener, code was also added to expand the node corresponding to 11, which runs after a 15-second delay. Here is the extra code for this:
Timer timer = new Timer(15000, new ActionListener() { public void actionPerformed(ActionEvent evt) { DefaultMutableTreeNode rootNode = (DefaultMutableTreeNode)t.getModel().getRoot(); DefaultMutableTreeNode apolloNode = (DefaultMutableTreeNode)rootNode.getFirstChild(); DefaultMutableTreeNode apollo11Node = (DefaultMutableTreeNode)apolloNode.getFirstChild(); // Convert the node to a TreePath TreeNode[] pathToRoot = apollo11Node.getPath(); TreePath path = new TreePath(pathToRoot); // Expand the node t.expandPath(path); } }); timer.setRepeats(false); timer.start();
The first problem is to find the node that needs to be opened. This is achieved by getting the root node from the tree's model and then using the getFirstChild method of DefaultMutableTreeNode to walk down through the various levels until the target is reached. DefaultMutable- TreeNode has several methods that allow you to access related nodeslook at its API documentation to find out what they are.
Having found the target node, it must be converted to a TreePath, for which the technique shown earlier is used, then the node can finally be expanded. If you start the program and do nothing for 15 seconds, you'll find that the tree opens to show the crew of Apollo 11, and three events are generated, one for the target node and one for each level above the target that was expanded automatically to make the target node visible:
Expansion event, path [null] Expansion event, path [null, Apollo] Expansion event, path [null, Apollo, 11]