The Java Drag and Drop API allows us to write code where the user can drag JComponents and drop them (or their attributes) onto another JComponent. The basis of the Drag and Drop API is the TransferHandler class.
There are some existing JComponents that support Drag and Drop with little extra work. You simply need to invoke setDragEnabled(true) for the following JComponents to allow for dragging them:
- JColorChooser
- JEditorPane
- JFileChooser
- JFormattedTextField
- JList
- JTable
- JTextArea
- JTextField
- JTextPane
- JTree
The components that support dropping already include:
- JEditorPane
- JFormattedTextField
- JPasswordField
- JTextArea
- JTextField
- JTextPane
- JColorChooser
Basics of Dragging
For those JComponents that do not support Drag-and-Drop by default, or JComponents you wish to customize their Drag-and-Drop behaviors, you need to pass them a new TransferHandler. The easiest way to create a TransferHandler is to instantiate one and pass it a beans property, or the name of a get/set method in the class (ie., text and icon are beans properties for JButton). We also need a MouseListener to export the drag.
JButton button = new JButton("This is the text");
TransferHandler transfer = new TransferHandler("text");
//the JButton can now be dragged and the text will be dropped
button.setTransferHandler(transfer);
//add a MouseListener to initiate the Drag on the appropriate
//MouseEvent
button.addMouseListener(new MouseAdapter(){
public void mousePressed(MouseEvent e){
JButton button = (JButton)e.getSource();
TransferHandler handle = button.getTransferHandler();
handle.exportAsDrag(button, e, TransferHandler.COPY);
}
});
Custom Dragging
In this section, we will explore custom dragging by creating a custom JButton we can actually drop, not just its text or icon, but the actual JButton. In addition to JButton and TransferHandler, we will be looking at the DragSource class, the Transferable interface, the DragSourceListener interface, and the DragGestureListener interface.
The way the Drag process works is that the JButton will listen for the DragGestureEvent. It will then use the DragSource to initiate the Drag. The TransferHandler will then export a Transferable, which wraps around the data you want to be transferred. In this case the DnDButton is a Transferable, exporting a new DnDButton with the same text on a drag.
/**
* Our custom JButton class that is Draggable.
* This JButton is Transferable (so it can be Dragged),
* And listens for its own drags
* */
public class DnDButton extends JButton implements Transferable,
DragSourceListener, DragGestureListener{
//marks this JButton as the source of the Drag
private DragSource source;
private TransferHandler t;
public DnDButton(){
this("");
}
public DnDButton(String message){
super(message);
//The TransferHandler returns a new DnDButton
//to be transferred in the Drag
t = new TransferHandler(){
public Transferable createTransferable(JComponent c){
return new DnDButton(getText());
}
};
setTransferHandler(t);
//The Drag will copy the DnDButton rather than moving it
source = new DragSource();
source.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_COPY, this);
}
//The DataFlavor is a marker to let the DropTarget know how to
//handle the Transferable
public DataFlavor[] getTransferDataFlavors() {
return new DataFlavor[]{new DataFlavor(DnDButton.class, "JButton")};
}
public boolean isDataFlavorSupported(DataFlavor flavor) {
return true;
}
public Object getTransferData(DataFlavor flavor) {
return this;
}
public void dragEnter(DragSourceDragEvent dsde) {}
public void dragOver(DragSourceDragEvent dsde) {}
public void dropActionchanged(DragSourceDragEvent dsde) {}
public void dragExit(DragSourceEvent dse) {}
//when the drag finishes, then repaint the DnDButton
//so it doesn't look like it has still been pressed down
public void dragDropEnd(DragSourceDropEvent dsde) {
repaint();
}
//when a DragGesture is recognized, initiate the Drag
public void dragGestureRecognized(DragGestureEvent dge) {
source.startDrag(dge, DragSource.DefaultMoveDrop, new DnDButton("Text"), this);
}
}//end outer class









MultiQuote






|