17.6 Tree Events


Trees generate three types of events worth mentioning. Apart from the obvious selection events (TreeSelectionEvent, TreeSelectionListener), you can receive expansion events (TreeExpansionEvent, TreeExpansionListener, TreeWillExpandListener) from the graphical side, and you can catch structural changes to the model itself (TreeModelEvent, TreeModelListener).

Figure 17-9 shows a simple program that uses the Every Event Listener (EEL) class (described in Chapter 3) to display all events that come from selecting, expanding, and editing a tree. (We use a tree built by the default JTree constructor.) For editing, you can change the text of a node or add and remove nodes so that you can monitor model events.

Figure 17-9. The JTree events as reported by our EEL utility
figs/swng2.1709.gif

Here's the source code required to hook up all the various events:

// TreeEvents.java // import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.event.*; import javax.swing.tree.*; public class TreeEvents extends JFrame implements TreeSelectionListener {   JButton addB, deleteB;   JTree tree;   DefaultMutableTreeNode leadSelection;   public TreeEvents( ) {     super("Tree Event Demo");     setSize(300,200);     setDefaultCloseOperation(EXIT_ON_CLOSE);     EEL eel = EEL.getInstance( );     eel.addGui( );     tree = new JTree( );     tree.setExpandsSelectedPaths(true);     tree.setEditable(true);     getContentPane( ).add(new JScrollPane(tree), BorderLayout.CENTER);     tree.addTreeSelectionListener(eel);     tree.addTreeSelectionListener(this);     tree.addTreeExpansionListener(eel);     tree.addTreeWillExpandListener(eel);     tree.addPropertyChangeListener(eel);     tree.getModel( ).addTreeModelListener(eel);     addB = new JButton("Add a node");     deleteB = new JButton("Delete a node");     JPanel buttonP = new JPanel( );     buttonP.add(addB);     buttonP.add(deleteB);     getContentPane( ).add(buttonP, BorderLayout.SOUTH);     addB.addActionListener(new ActionListener( ) {         public void actionPerformed(ActionEvent ae) {           String nodeName = JOptionPane.showInputDialog("New node name:");           if (leadSelection != null) {             leadSelection.add(new DefaultMutableTreeNode(nodeName));             ((DefaultTreeModel)tree.getModel( )).reload(leadSelection);           }           else {             JOptionPane.showMessageDialog(TreeEvents.this, "No Parent...");           }         }       });     deleteB.addActionListener(new ActionListener( ) {         public void actionPerformed(ActionEvent ae) {           if (leadSelection != null) {             DefaultMutableTreeNode parent =                (DefaultMutableTreeNode) leadSelection.getParent( );             if (parent == null) {               JOptionPane.showMessageDialog(TreeEvents.this, "Can't delete root");             }             else {               parent.remove(leadSelection);               leadSelection = null;               ((DefaultTreeModel)tree.getModel( )).reload(parent);             }           }           else {             JOptionPane.showMessageDialog(TreeEvents.this, "No Selection...");           }         }       });     eel.showDialog( );   }   public void valueChanged(TreeSelectionEvent e) {     TreePath leadPath = e.getNewLeadSelectionPath( );     if (leadPath != null) {       leadSelection = (DefaultMutableTreeNode)leadPath.getLastPathComponent( );     }   }   public static void main(String args[]) {     TreeEvents te = new TreeEvents( );     te.setVisible(true);   } }

17.6.1 The TreeModelEvent Class

The TreeModelEvent class encapsulates model changes by specifying the path that has changed as well as information on the children of that path.

17.6.1.1 Properties

The TreeModelEvent has several properties as shown in Table 17-15. If the event contains information about the affected children of a node, you can retrieve the indices and the children themselves with the childIndices and children properties, respectively. The path and treePath properties provide access to the main node of the event. Whether you look at that node through a TreePath object or through an Object array depends on your program; both methods lead to the same node.

Table 17-15. TreeModelEvent properties

Property

Data type

get

is

set

Default value

childIndices

int[]

·

     

children

Object[]

·

     

path

Object[]

·

     

treePath

TreePath

·

     

17.6.1.2 Constructors
public TreeModelEvent(Object source, Object path[], int childIndices[], Object children[])
public TreeModelEvent(Object source, TreePath path, int childIndices[], Object children[])

Allow you to build an event that encompasses the children of a modified node. This type of event is useful if the references to the node's children have changed, or if the number of children has changed.

public TreeModelEvent(Object source, Object path[])
public TreeModelEvent(Object source TreePath path)

If the modified node is the only interesting node for this event (if its value changed, but nothing happened to its children, for example), you can use these constructors.

17.6.2 The TreeModelListener Interface

The TreeModelListener interface requires that listeners implement the following methods:

public void treeNodesChanged(TreeModelEvent e)
public void treeNodesInserted(TreeModelEvent e)
public void treeNodesRemoved(TreeModelEvent e)

Indicate that nodes were changed, inserted, or removed, respectively.

public void treeStructureChanged(TreeModelEvent e)

Indicate that the tree structure has changed significantly (such as several subtrees being deleted) and may require more analysis than can be performed on the nodes and children retrievable through the event object e.

We can use this class of events to monitor the state of the tree. For example, consider a tree that represents a filesystem. Any time we change the tree, we want to update the supporting filesystem. Listening for model changes would be the precise clue we need to perform the required updates.

17.6.3 The TreeSelectionEvent Class

Selection events occur whenever a user (or program, for that matter) changes the selection on a tree. For example, if you went through a directory tree and manually selected 12 discontiguous files, that would generate 12 selection events, each building on the last. If you were to pick 12 contiguous files by selecting the first file and using a modifier to pick the last, that would generate only two selection events. (Both of these examples assume that nothing was originally selected.) As with list selections, unselecting something also counts as a selection event. In many cases where more than one file can be selected, you shouldn't listen for selection events directly, but rather provide an OK button or some other means for the user to finalize the current selection.

17.6.3.1 Properties

The properties for TreeSelectionEvent are shown in Table 17-16. Not surprisingly, they are similar to the selection properties available for the JTree class.

Table 17-16. TreeSelectionEvent properties

Property

Data type

get

is

set

Default value

addedPath

boolean

 

·

 

Set by constructor

newLeadSelectionPath

TreePath

·

   

Set by constructor

oldLeadSelectionPath

TreePath

·

   

Set by constructor

path

TreePath

·

   

Set by constructor

paths

TreePath[]

·

   

Set by constructor

17.6.3.2 Constructors
public TreeSelectionEvent(Object source, TreePath path, boolean isNew, TreePath oldLeadSelectionPath, TreePath newLeadSelectionPath)

Build a TreeSelectionEvent centered on one path. The isNew argument determines whether the selection is an addition to (true) or a removal from (false) the current selection.

public TreeSelectionEvent(Object source, TreePath paths[], boolean areNew[], TreePath oldLeadSelectionPath, TreePath newLeadSelectionPath)

Build a selection event that starts off with multiple selections in place. This would be useful in a filesystem tree for selecting things that matched a filter, like all the .java files.

17.6.3.3 Methods
public Object cloneWithSource(Object newSource)

This clever method allows you to clone an event and modify the source component that ostensibly generated the event. This is great for a component that delegates some or all of its visual presence to a tree. You can use this method in an event adapter to pass on the event to some other listener, with the new component listed as the source.

public boolean isAddedPath(int index)
public boolean isAddedPath(TreePath path)

Check an arbitrary specified path or index to see if it was added to the current selection. This can be useful if you are interested in the status of a single path but the event was generated with an array of new paths.

17.6.4 The TreeSelectionListener Interface

The TreeSelectionListener interface carries only one method:

public void valueChanged(TreeSelectionEvent e)

Called whenever the selection on a tree changes. The DefaultTreeModel uses this method even for selections caused programmatically.

17.6.5 The TreeExpansionEvent Class

Normally, the tree UI expands and collapses elements of a tree for you. However, if you want to listen for and react to these events, you can do so. The TreeExpansionEvent class covers both expanding and collapsing a tree node.

17.6.5.1 Property

The sole property for TreeExpansionEvent is shown in Table 17-17.

Table 17-17. TreeExpansionEvent property

Property

Data type

get

is

set

Default value

path

TreePath

·

   

Set by constructor

17.6.5.2 Constructor
public TreeExpansionEvent(Object source, TreePath path)

The source for this constructor is most often the tree itself, but it's certainly possible to imagine a GUI trigger as the source for a collapse or expand call.

17.6.6 The TreeExpansionListener Interface

To catch expansion or collapse events yourself, you can implement the TreeExpansionListener interface, which provides the following two methods:

public void treeExpanded(TreeExpansionEvent e)
public void treeCollapsed(TreeExpansionEvent e)

Called when a path is collapsed or expanded.

17.6.7 Pending Expansion Events

JDK 1.2 introduced two classes that help you listen and react to expansion events before they occur. The TreeWillExpandListener interface allows you to register interest in pending expansion events. Implementations of this interface throw an ExpandVetoException if they decide that the expansion or collapse should not be allowed.

17.6.7.1 The TreeWillExpandListener interface

This interface gives you access to the expansion events (both expanding and collapsing) before the event takes place in the tree itself. The only reason you would want to hear about such an event rather than listening for the real expansion event is if you want to do something with the tree before it changes. The interface provides the following two methods:

public void treeWillExpand(TreeExpansionEvent event) throws ExpandVetoException
public void treeWillCollapse(TreeExpansionEvent event) throws ExpandVetoException

Implement these methods to react to pending expansion events.

17.6.7.2 The ExpandVetoException class

The most common reason for listening to pending expansion events is that you may want to stop them from occurring. If the user does not have permission to expand a folder in a filesystem, for example, you could have a listener check each expand event. If you find a case where an expansion or collapse should not occur, your listener can throw an ExpandVetoException. Each of the listener methods mentioned above can throw this exception. The JTree setExpandedState( ) method catches these exceptions, and, if one is thrown, the node is left alone, and the fireTreeExpanded( ) or fireTreeCollapsed( ) method is never called. ExpandVetoException's constructors are:

public ExpandVetoException(TreeExpansionEvent event)
public ExpandVetoException(TreeExpansionEvent event, String message)

Similar to other exception classes, these constructors build new exceptions with the proposed expansion event and an optional message.



Java Swing
Graphic Java 2: Mastering the Jfc, By Geary, 3Rd Edition, Volume 2: Swing
ISBN: 0130796670
EAN: 2147483647
Year: 2001
Pages: 289
Authors: David Geary

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net