14.1 Simple Swing Data Transfer
We begin with an examination of the built-in data transfer
capabilities of Swing components and how to
perform simple customizations. As a general rule, Swing components
that display text and allow it to be selected
(JList and JTable, for example,
but not JLabel) support Copy and Drag
operations. Components that display editable text typically support
Cut, Paste, and Drop operations as well.
JPasswordField is a special case: it supports
Paste and Drop, but because of the sensitivity of password data, does
not allow its masked text to be dragged, cut, or copied to the
clipboard. Finally, JColorChooser allows colors to
be dragged, and JFileChooser allows files to be
dragged.Swing components that support dragging do not enable it by default.
To enable drags in a component that supports it, pass
true to setDragEnabled(
). Components that do not support dragging
at all do not define this setDragEnabled( )
method.Swing data transfer is enabled by a
TransferHandler object. Components that support data
transfer by default have a default TransferHandler
installed. The TransferHandler( ) constructor
method takes a JavaBeans property name as its sole argument. A
TransferHandler created in this way is responsible
for transferring the value of the named property. In a Cut, Copy, or
Drag operation, it reads the value of the named property and makes it
available for transfer. In a Paste or Drop operation, it reads the
transferred data and then attempts to set the named property to the
specified value. If the named property is read-only, the
TransferHandler will enable only Copy and Drag
operations, not Cut, Paste, or Drop operations. If the data to be
transferred is not available through a property, or if you want to
support pastes and drops of more than one type of data, you can
subclass TransferHandler to add these
capabilities.Example 14-1 illustrates two simple customizations of
the default Swing data transfer behavior. First, it registers custom
TransferHandler objects to support Drag and Drop
of colors. Second, it enables Drag operations from a
JLabel component by registering a
MouseMotionListener to detect drag gestures and
initiate the drag through the TransferHandler.
When you run the program, it allows you to drag the foreground color
of the first JLabel and drop it on the second
JLabel, which will use the dropped color as its
background. This example is more interesting if you also display a
JColorChooser component at the same time, using
the ShowBean program of Chapter 11. To enable drags from the
JColorChooser, you must set its
dragEnabled property:
java je3.gui.ShowBean javax.swing.JColorChooser dragEnabled=true
Note that the JColorChooser component does not
allow drags from the tiny color swatches in the main part of the
window. Instead, you must select a color and then drag it from the
sample swatch at the bottom of the window.
Example 14-1. ColorDrag.java
package je3.datatransfer;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
/**
* Simple Drag-and-Drop customization:
drag the foreground color from the first
* label and drop it as the background color into the second one.
Try it also
* using the ShowBean program to display a JColorChooser
component with
* dragEnabled=true.
*/
public class ColorDrag {
public static void main(String args[ ]) {
// Create two JLabel objects
final JLabel label1 = new JLabel("Drag here");
JLabel label2 = new JLabel("Drop here");
// Register TransferHandler objects on them: label1 transfers its
// foreground color and label2 transfers its background color.
label1.setTransferHandler(new TransferHandler("foreground"));
label2.setTransferHandler(new TransferHandler("background"));
// Give label1 a foreground color other than the default
// Make label2 opaque so it displays its background color
label1.setForeground(new Color(100, 100, 200));
label2.setOpaque(true);
// Now look for drag gestures over label1. When one occurs,
// tell the TransferHandler to begin a drag.
// Exercise: modify this gesture recognition so that the drag doesn't
// begin until the mouse has moved 4 pixels. This helps to keep
// drags distinct from sloppy clicks. To do this, you'll need both
// a MouseListener and a MouseMotionListener.
label1.addMouseMotionListener(new MouseMotionAdapter( ) {
public void mouseDragged(MouseEvent e) {
TransferHandler handler = label1.getTransferHandler( );
handler.exportAsDrag(label1, e, TransferHandler.COPY);
}
});
// Create a window, add the labels, and make it all visible.
JFrame f = new JFrame("ColorDrag");
f.getContentPane( ).setLayout(new FlowLayout( ));
f.getContentPane( ).add(label1);
f.getContentPane( ).add(label2);
f.pack( );
f.setVisible(true);
}
}