How to drag and drop with Java 2, Part 2

Create a library of drag and drop-enabled Swing components

1 2 3 Page 3
Page 3 of 3

Dialogs

Let's say that the user has just dropped a duplicate item onto a DnDList, and you would like to ask if he or she really would like two copies of that item in the list. You cannot show a dialog that requires input during a D&D operation (that is, in one of the listener's callbacks) without the risk of deadlock. You might be able to get away with displaying a message dialog that is shown via SwingUtilies.invokeLater without deadlock. However, if you would like the JOptionPane to show, say, a confirm dialog, you need to use the SwingWorker class. This isn't a standard class in the JDK, but you can download it from the Swing Connection (see Resources).

The second example (Example2.java) of using the SwingWorker class requires only a little modification to work with D&D. You create an instance of a SwingWorker in the add() method that is called when the data is dropped. The waitForUserConfirmation() method can be modified for the dialog of your choice. The doWork() method needs to return a boolean value based on the input from the dialog. This boolean value may be retrieved in the SwingWorker's finished method by the get() method. If the value is true, go ahead and add the item; otherwise, do nothing. If it's a local operation, the user is rearranging items and a duplicate already exists. In that case, you should not show the dialog.

Deficiencies

There are some problems in the JDK that you should be aware of when using D&D. This section will identify them and present known workarounds.

Caret problem

Text components work well as drop sites. You can't drag from them, however, since the drag gesture interferes with the caret.

Clipboard

The sun.awt.windows.WClipboard class currently uses instanceof StringSelection instead of checking the MIME type. A custom text flavor works well with D&D, but not with the clipboard.

Cursor feedback

Setting a custom cursor during dragEnter or dragOver causes it to flicker between the default platform cursor and your custom cursor. One workaround is to set the cursor to null and then set it to your custom cursor.

JTabbedPane

There is a problem with dragging and dropping children of a JTabbedPane. It seems to work only on the first tab. Actually, it will return a child from the first tab even if another tab is selected. The solution is to create a subclass of JTabbbedPane to override the findComponentAt() method inherited from java.awt.Container. You can simply add a check to the existing code to see if the container (current tab) is visible.

CardLayout

D&D doesn't work with the CardLayout manager. There is no known workaround at this time.

Conclusion

Even though there are several problems using D&D with Swing components, we have found solutions or workarounds for many of them. In addition, rather than rewriting the same D&D code over and over again, we have developed a library of adapters and abstract classes that can be used and/or subclassed for each new D&D-enabled component.

Gene De Lisa is a senior consultant/instructor and curriculum developer for Rockhopper Technologies Inc. He has been developing and teaching Java since the fall of 1995. Since the beginning of 1998 his teaching and development has centered around Enterprise JavaBeans, and he has most recently focused on J2EE. His original drag and drop development was for EJB clients. He recently delivered a technical session on drag and drop at the 1999 JavaOne conference. He is also an amateur spheniscologist. You can see him turn into his favorite spheniscid species in an Applet on his Web page. (He's the one with the tie.)

Learn more about this topic

Related:
1 2 3 Page 3
Page 3 of 3