Drag with style in Swing

You can run the WebStart demo or, as usual, download its source code.

One very cool way to create user friendly interfaces is to provide the ability to drag and drop just about anything from, within and onto the application. MacOS X is a perfect example of a good drag and drop use. Everytime I try to drag something to drop it onto something else, it works. At least given you're not trying to perform something stupid like dropping a text file onto a game icon. Anyway, Windows and Linux let the applications implement drag and drop but they lack something MacOS X already offers: really cool visual feedback. For instance, dragging a picture from Safari, the web browser, shows a nice translucent thumbnail of the object. The user always knows what he is exactly dragging.

How could we then get rid of the simplistic drag and drop cursor that Java provides us? The solution lies in the Drag n' Ghost Demo I'm about to show you. See for yourself, don't you like this nice translucent picture?

Dragging a picture is cool but what if we could drag just about any components and still get that nice effect? No problem folks:

Still not convinced, see what dragging a whole, fully loaded JTable looks like:

Now that I have your attention, let's see how to use it in your applications. The trick is to use a glass pane to paint the translucent picture of the components over the UI. Therefore, you must set the GhostGlassPane to the frame and then attach a GhostDropAdapter and a GhostMotionAdapter to the component you want to be able to drag and drop:

GhostGlassPane glassPane = new GhostGlassPane();

JLabel label = new JLabel("Component adapted");
label.addMouseListener(new GhostComponentAdapter(glassPane, "action_1"));
label.addMouseMotionListener(new GhostMotionAdapter(glassPane));

JButton button = new JButton("Picture adapted");
label.addMouseListener(new GhostPictureAdapter(glassPane, "action_2", "image.png"));
label.addMouseMotionListener(new GhostMotionAdapter(glassPane));

And that's it, it is as simple as that. You may have noticed we do not use a GhostDropAdapter but its two subclasses, GhostComponentAdapter and GhostPictureAdapter. The first one creates the ghost picture by painting the source component in an offscreen image whereas the second one uses the ghost picture you provided.

Every GhostDropAdapter can register GhostDropListeners which are invoked when the drop occurs. The event is an instance of GhostDropEvent which gives you the action name and the location of the drop. Since the location is in screen coordinates, it is advised to use the AbstractGhostDropManager which provides two interesting methods.

Such a manager is tied to a component (see the constructor) called the target. Two methods let you handle the target component: isInTarget() checks whether the drop location is located within the bounds of the target component and getTranslatedPoint() translates the screen coordinates into target coordinates. The GhostDropManagerDemo shows how to create a custom manager. In this case, the manager waits for a drop onto the JTable and pops up the action name:

The GhostDrop components set suffers from two problems though. First, performances can be quite bad when you drag a ghost over a large window. I've seen it happen only on my computer but I have no doubt it will happen on some of yours too. I can't see how to optimize the rendering apart from using a VolatileImage (and I'm not sure of the result). The second problem happens when the focus is given to another window while you're dragging something. The ghost remains painted on the glass pane. I think this can be fixed quite easily by listening to the focus of the parent window.

2 Responses to “Drag with style in Swing”

  1. markharold says:

    Romain is there a way we can set up multiple drop target points? For example drop events can be also recieved by the New Sale Image Button and Drag n’ Drop Button.

  2. Klogd says:

    Neat, what is the license of the source code? GPL? LGPL?