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(); setGlassPane(glassPane); 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,
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.
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.