Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Java Tip 97: Add drag and drop to your JTrees

Improve JTree usability with drag and drop

  • Digg
  • Reddit
  • SlashDot
  • Stumble
  • del.icio.us
  • Technorati
  • dzone
Implementing 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:

  • Digg
  • Reddit
  • SlashDot
  • Stumble
  • del.icio.us
  • Technorati
  • dzone
Comment
Login
Forgot your account info?
Add comment
Anonymous comments subject to approval. Register here for member benefits.
Have a JavaWorld account? Log in here. Register now for a free account.
Resources