How would you like to drag and drop almost any kind of data using almost any project Swing component? The first article in this
series, "How to drag and drop with Java 2" (see Resources), introduced data transfer using familiar drag and drop (D&D) gestures. The
first article's examples were limited to a single project Swing component -- a D&D-enabled JLabel. We transferred text data between
Sign In | Register
labels in the same Java virtual machine (JVM), to other JVMs, and to the native system.
This article will show you how to create D&D-enabled versions of many more Swing components. We'll also learn how to transfer
various data types beyond plain text.
An important point to remember is that a is serializable. If the resides in the same JVM, it will receive a
reference to a live object. If, however, the is in a different JVM, it will receive a serialized copy of the . The D&D
system automatically serializes the in the same way that RMI parameters are marshalled. We can easily transfer any data
encapsulated in a serializable object by defining our own class.
publicclassRockhopperextendsBirdimplementsSerializable
privateString//Stringisserializable
publicclassRockhopperTransferable
implementsTransferable
ClipboardOwner
publicstaticDataFlavor null
publicstaticDataFlavor null
static
try
new
DataFlavorRockhopperclass
new
DataFlavorDataFlavor
catchException
System
privateRockhopper
publicRockhopperTransferableRockhopper
this
publicObject
//checktoseeiftherequestedflavormatches
returnthis//easy!
You may want to create a library of classes for commonly used data types. Popular custom choices
include , , , and .
A D&D-enabled component would create associations with an instance of each of these classes, as shown in Figure 1.
Transferable models
For some components, we might not want to create an individual subclass for each type of data the component might represent. It
would be better to create a transferable model for these components. When the drag operation starts, the component gets the
from the model. This strategy works well for the JTable and JList.
JList
It is convenient to place all of the common D&D methods in an abstract subclass of JList. This abstract takes care of creating
and registering the appropriate adapters, drag-under and drag-over feedback, autoscrolling, moving, and event/flavor validation. The
concrete subclass specifies the acceptable operations and flavors, and defines an method that is called when the
receives the drop message.
We can define a interface with method . For convenience,
we can define an model that has data structure maintenance code but requires that subclasses implement the
method. This concrete subclass determines the exact type of returned. For example, a
concrete subclass of would create a concrete subclass of ; the latter in turn creates and
returns a object from .
JTable
The JTable follows the same pattern as the JList. We place the common D&D code in an abstract class that uses an abstract
transferable model. The concrete table subclasses create a concrete transferable model.
JTree
It isn't necessary to create a model for the JTree. The tree nodes may contain a user object. If this object is serializable,
you can define a class with a that uses a as its representation class.
What does it mean to copy a tree node? Do you want to copy just the node, or all of its children? We will address these issues below,
when we talk about the JTree in more detail.
When you create a D&D-enabled component, there are several issues you need to address:
Starting the drag operation
Drag-under feedback
Drag-over feedback
The drop
Drag-under feedback
How do we show that a drop is valid? If, for example, the component is a JList, where will the drop occur? To show the user where
the data will be inserted, define the and methods from our interface.
Drag-over feedback
Most of the time, the default drag-over feedback is fine. However, there could be a situation in which you would like to use custom
cursors. The calls the 's method repeatedly during the drag. The return value sets the
drag-over feedback. For most components the initial cursor should be a no-drop cursor, since dropping the data in the same place as
its origin is useless.
The drop
If you accept the dropped data, you insert it someplace in the component. Where is it going to be inserted? What flavors are
accepted?
Transferable
What / class should you use? When a drag starts, how do you get the object? The
object may encapsulate data associated with the component or data retrieved from its model. Our
calls the
's method.
JList
Now, let's look at possible solutions for each of the issues we've just raised in the context of a D&D-enabled JList.
Drag-under feedback
NEXT
View 1 Comment