Programming Tutorials Browser Tutorials Articles Struts Tutorials Hibernate Tutorials

  Tutorial: Add drag and drop to your JTrees - JavaWorld Tip 97

Add drag and drop to your JTrees - JavaWorld Tip 97

Tutorial Details:

Java Tip 97: Add drag and drop to your JTrees
Java Tip 97: Add drag and drop to your JTrees
By: By Rob Kenworthy
Improve JTree usability with drag and drop
mplementing drag and drop lets users manipulate data with simple mouse movements and can mean the difference between an efficient or cumbersome application. Unfortunately, one of the more useful and powerful GUI components, JTree, comes without built-in support for drag and drop. Applications often address that issue by adding menu items to the frame containing the JTree. But an even better solution would be to implement drag and drop in the JTree itself. Its implementation can be complicated, but this article will guide you through the process, step by step.
Unlike simple GUI components, JTree objects contain substructure, which makes implementing drag and drop for JTree controls more difficult than for simpler GUI components. In fact, I read in one newsgroup thread that adding drag and drop to a JTree is impossible.
The big stumbling block is that since the JTree's nodes are the objects being dragged, it appears that they should implement the drag-and-drop interfaces.
The truth is that each node is completely unaware that it is even contained in a JTree; there is no getTree() in the TreeNode interface. Hence, the drag and drop interfaces must be implemented by the class listening for the JTree events.
Setup
For illustration purposes, let's consider a JTree that displays a family tree. All females in the tree may have children. Males in the tree don't have children. To distinguish between node types, you can force the male node icon to be the leaf icon and females to be the internal node icon (which is a folder and implies the ability to have children). To do that, you need to override the isLeaf() and getAllowsChildren() methods of the DefaultMutableTreeNode class (there are other ways, but that's probably the easiest). Only one class is used for all the node objects, male and female. If a node is male, the isLeaf() method will always return true and the getAllowsChildren() method will always return false. The code will look similar to the following:
public boolean isLeaf() {
return isMale;
}
public boolean getAllowsChildren() {
return !isMale;
}
Details
I'll continue by examining the specific drag-and-drop interfaces. From the java.awt.dnd package, there are DragGestureListener (drag gesture recognizer), DragSourceListener (drag source), and DropTargetListener (drop target). From the java.awt.datatransfer package, there is Transferable .
The Transferable interface will be implemented by the object that encapsulates the node data, but the rest of the interfaces will be implemented by the class that listens to the JTree events (presumably a class that subclasses JTree).
DragGestureListener
The DragGestureListener interface is invoked when a DragGestureRecognizer object detects a drag-initiating gesture.
Below is an example code listing of this interface's only method. Its code will start the drag action.
1 public void dragGestureRecognized(DragGestureEvent e) {
2 DefaultMutableTreeNode dragNode = getSelectedNode();
3
4 if (dragNode != null) {
5 Transferable transferable =
6 (Transferable) dragNode.getUserObject();
7
8 Cursor cursor = selectCursor (e.getDragAction())
9
10 dragSource.startDrag(e, cursor, transferable, this);
11 }
12 }
13
14 private Cursor selectCursor (int action) {
15 return (action == DnDConstants.ACTION_MOVE) ?
16 DragSource.DefaultMoveDrop : DragSource.DefaultCopyDrop;
17 }
The following list explains the steps you take in Lines 2 through 10 in the above code:
Line 2: You grab the node that will be dragged. (You will have to implement getSelectedNode() .)
Lines 5-6: You grab the object you wish to transfer (more about the Transferable object later).
Lines 8 : You set the drag cursor type appropriately.
Line 10: You start the drag event. Its parameters are as follows:
e is the DragGestureEvent
cursor is the cursor you wish to use
transferable is the object to be transferred
dragSourceListener is the component that has implemented the DragSourceListener interface
DragSourceListener
The DragSourceListener interface is implemented by the component that contains the draggable object. There are five possible drag actions, and the DragSourceListener has a method to handle each one. The code in those methods is not required. Some of them can be left empty, but the dragEnter and dragOver are useful for setting the cursor type to indicate whether the drop target is valid. I'll revisit how you do this later in the article.
DropTargetListener
The DropTargetListener interface is implemented by the component that will drop the object. Once again, there are five possible drop actions and the DropTargetListener has a method to handle each one. You use the dragOver method to obtain the cursor location and decide if the drop location is valid, but the most interesting method is the drop method. Below is an example code listing of that method. Its code completes the desired action to take when a drop action occurs.
//The Drag operation has terminated with a Drop on this DropTarget
1 void drop(DropTargetDropEvent dtde) {
2 Transferable transferable = dtde.getTransferable();
3
4 //flavor not supported, reject drop
5 if (!transferable.isDataFlavorSupported( )) {
6 e.rejectDrop();
7 return;
8 }
9
10 DefaultMutableTreeNode oldParent =
getSelectedNode().getParent();
11
12 Point loc = dtde.getLocation();
13 TreePath destinationPath = getPathForLocation(loc.x, loc.y);
14 DefaultMutableTreeNode newParent =
15 (DefaultMutableTreeNode)
destinationPath.getLastPathComponent();
16
17 DefaultMutableTreeNode newChild = null;
18 if (dtde.getDropAction() == DnDConstants.ACTION_COPY) {
//make a new child
19 Object data = tranferable.getTransferData( );
20 DefaultMutableTreeNode newChild = new
DefaultMutableTreeNode(data.clone());
21 }
22 else { //move
23 newChild = getSelectedNode();
24 oldParent.remove(newChild);
25 }
26
27 newParent.add(child);
28 }
Here's an explanation of the steps taken in the above code:
Line 2: You grab the Transferable object.
Lines 4-8: You verify that the flavor of data you want is supported. If not, then cancel. Above, I have used the notation to indicate the flavor. That constant is of DataFlavor type and can be user-defined or one of the flavors found within the DataFlavor class. This is just sample code, so you don't know what flavor it is.
Lines 10-15: You retrieve the old and new parent nodes.
Line 17-24: Based on the action, you determine the newChild . If it's a copy, then clone the data and make newChild a new DefaultMutableTreeNode with the cloned data as the user object. Otherwise, set newChild to be the old child and remove it from the old parent.
Line 27: You add the new child to its new parent.
Note that the code above is shortened for the sake of clarity and neglects error-handling code. If you want to cut and paste, refer to DnDJTree.java in the source code zip in Resources for a more production-worthy example.
Transferable
The Transferable interface is where the supported DataFlavors are defined and is used to obtain the transferable data. The data flavors are simply the different formats of data that can be transferred. They are most useful when transferring data, via drag and drop, out of or into the JVM environment. Transfers outside of the JVM use MIME formats, which are an Internet standard system for identifying types of encapsulated data.
Here are some examples of data flavors taken from java.awt.datatransfer.DataFlavor :
javaFileListFlavor : To transfer a list of files to/from Java (and the underlying platform), you use a DataFlavor of this type/subtype and representation class of java.util.List .
javaJVMLocalObjectMimeType : This flavor is used to transfer an arbitrary Java object reference with no associated MIME type within the same JVM.
javaRemoteObjectMimeType : To pass a live link to a remote object via a drag-and-drop ACTION_LINK operation, you should use a Mime Content Type of application/x-java-remote-object, in which the representation class of the DataFlavor represents the type of remote interface to be transferred.
javaSerializedObjectMimeType : A MIME Content Type of application/x-java-serialized-object represents a graph of Java object(s) that have been made persistent.
plainTextFlavor : The DataFlavor representing plain text with unicode encoding, where:
representationClass = InputStream
mimeType = "text/plain; charset=unicode"
stringFlavor : The DataFlavor representing a Java Unicode String class, where:
representationClass = java.lang.String
mimeType = "application/x-java-serialized-object"
The Transferable interface is implemented by any object hat can be transferred using drag and drop. However, if you are only transferring text, you can use the Java-predefined DataFlavor , java.awt.datatransfer.StringSelection . Otherwise, your new Transferable object must contain implementations of several methods, similar to the code fragments below:
1 public Object getTransferData(DataFlavor df)
2 throws UnsupportedFlavorException, IOException {
3 if (df.equals( ) == false)
4 throw new UnsupportedFlavorException(df)
5 return this;
6 }
Line 3 compares the DataFlavor parameter with the flavor that class supports. The class only supports one flavor, so it makes one comparison. However, it could support several flavors. If that were the case, it would cycle through checking for equality. Upon finding the right flavor, it would return the corresponding data. In line 5, you return the data associated with the DataFlavor parameter. In this example, you simply return this, but that assumes the class is the data. The data could have been anything you wanted (as described by the DataFlavor ).
The two other methods to implement are getTransferDataFlavors and isDataFlavorSupported . The purpose of those t


 

Read Tutorial at: Click here to view the tutorial

Rate Tutorial:
Add drag and drop to your JTrees - JavaWorld Tip 97

View Tutorial:
Add drag and drop to your JTrees - JavaWorld Tip 97

Related Tutorials:

Reloading Applets
Reloading Applets
 
Java Tip 72: Press Escape to close your Swing dialog windows
Java Tip 72: Press Escape to close your Swing dialog windows
 
Enhance your Java application with Java Native Interface (JNI)
Enhance your Java application with Java Native Interface (JNI)
 
Create a scrollable virtual desktop in Swing
Create a scrollable virtual desktop in Swing
 
Flex your grid layout
Flex your grid layout
 
Create a quick-and-dirty XML parser
Create a quick-and-dirty XML parser
 
Make a statement with javac!
Make a statement with javac!
 
Quickly access files and directories you use repeatedly
Quickly access files and directories you use repeatedly
 
Profiling CPU usage from within a Java application
Profiling CPU usage from within a Java application
 
roots of constants classes
roots of constants classes
 
Java Tip 143: Utilize the Database Schema Browser
Java Tip 143: Utilize the Database Schema Browser
 
ULC - J2EE Rich Clients now on Eclipse
ULC - J2EE Rich Clients now on Eclipse it is porting ULC Visual Editor to the new Eclipse visual GUI construction and editor platform. The company has been invited to participate in the Eclipse Visual Editor project. Following its decision to contribute
 
Filtering and Transforming Digital Images
Filtering and Transforming Digital Images In this Issue Welcome to the Core Java Technologies Tech Tips for April 7, 2004. Here you\'ll get tips on using core Java technologies and APIs, such as those in Java 2 Platform, Standard Edition (J2SE).
 
Hermes JMS Browser
Hermes JMS Browser Hermes is a Swing application that allows you to interact with JMS providers.
 
JGraph - The Java Graph Diagram Component
JGraph - The Java Graph Diagram Component JGraphAddons is a drop-in functional module that adds powerful and configurable layout algorithms to your existing JGraphs. They include hierarchical, circular and tree layouts capable of giving your JGraph app
 
JXMLPad 2.3
JXMLPad 2.3 JXMLPad is a pure Swing java component/framework for editing XML/XHTML document.
 
JXMLPad 3.1 FC
JXMLPad is a pure Swing java component/framework for editing XML/XHTML document.
 
Unclog the server bottleneck with active containers.
In server-side control architectures such as Java ServerFaces (JSF) or Struts, a majority of the control events must be handled on the server side to update the state of the control. For every user event, the entire page data is sent back to the server...
 
Writing a Custom Counter Component
MIDP 2.0 introduced the javax.microedition.lcdui.CustomItem class. As the name implies, a developer can now create custom UI components by extending the CustomItem class. This tech tip designs and implements a UI component for displaying a numeric counter
 
Locking Down Server Access to SSH With SunScreen Software (Community Submission)
This Tech Tip shows how to lock down a server to a group of client machines, allowing SSH access only, using SunScreen software.
 
Site navigation
 

 

Send your comments, Suggestions or Queries regarding this site at roseindia_net@yahoo.com.

Copyright © 2006. All rights reserved.