|
|
Строка 1: |
Строка 1: |
- | In computer graphical user interfaces, drag-and-drop is the action of (or support for the action of) clicking on a virtual object and dragging it to a different location or onto another virtual object. In general, it can be used to invoke many kinds of actions, or create various types of associations between two abstract objects. (Wikipedia)
| |
- | Drag and drop functionality is one of the most visible aspects of the graphical user interface. Drag and drop operation enables users to do complex things intuitively.
| |
| | | |
- | Usually, we can drag and drop two things. Data or some graphical objects. If we drag an image from one application to another, we drag and drop binary data. If we drag a tab in Firefox and move it to another place, we drag and drop a
| |
- | graphical component.
| |
- |
| |
- | The sheer amount of various classes involved with drag and drop operations in Java Swing toolkit might be overwhelming.
| |
- | The best way how to cope with this complexity is to create a small example for all situations. And slowly make it to more complex examples.
| |
- |
| |
- | <center>
| |
- | [[image: java_swing_dragdrop1.png | center]]
| |
- | </center>
| |
- |
| |
- | The component, where the drag operation begins must have a <b>DragSource</b> object registered. A <b>DropTarget</b> is an object responsible for accepting drops in an drag and drop operation. A <b>Transferable</b> encapsulates data being transferred. The transferred data can be of various type. A <b>DataFlavor</b> object provides information about the data being transferred.
| |
- |
| |
- | Several Swing components have already a built-in support for drag and drop operations. In such cases, a Swing programmer
| |
- | uses a <b>TransferHandler</b> to manage the drag and drop functionality. In situations, where there is no built-in support, the programmer has to create everything from scratch.
| |
- |
| |
- | == A simple drag and drop example ==
| |
- |
| |
- | We will demonstrate a simple drag and drop example. We will work with built-in drag and drop support. We will
| |
- | utilize a <b>TransferHandler</b> class.
| |
- |
| |
- | <source lang="java">
| |
- | import javax.swing.JButton;
| |
- | import javax.swing.JFrame;
| |
- | import javax.swing.JTextField;
| |
- | import javax.swing.TransferHandler;
| |
- |
| |
- |
| |
- | public class SimpleDnD extends JFrame {
| |
- |
| |
- | JTextField field;
| |
- | JButton button;
| |
- |
| |
- | public SimpleDnD() {
| |
- |
| |
- | setTitle("Simple Drag & Drop");
| |
- |
| |
- | setLayout(null);
| |
- |
| |
- | button = new JButton("Button");
| |
- | button.setBounds(200, 50, 90, 25);
| |
- |
| |
- | field = new JTextField();
| |
- | field.setBounds(30, 50, 150, 25);
| |
- |
| |
- | add(button);
| |
- | add(field);
| |
- |
| |
- | field.setDragEnabled(true);
| |
- | button.setTransferHandler(new TransferHandler("text"));
| |
- |
| |
- | setSize(330, 150);
| |
- | setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
| |
- | setLocationRelativeTo(null);
| |
- | setVisible(true);
| |
- | }
| |
- |
| |
- | public static void main(String[] args) {
| |
- | new SimpleDnD();
| |
- | }
| |
- | }
| |
- | </source>
| |
- |
| |
- | In our example we have a text field and a button. We can drag a text from the field and drop it onto the button.
| |
- |
| |
- | <source lang="java">
| |
- | field.setDragEnabled(true);
| |
- | </source>
| |
- |
| |
- | The text field has a built in support for dragging. We must enable it.
| |
- |
| |
- | <source lang="java">
| |
- | button.setTransferHandler(new TransferHandler("text"));
| |
- | </source>
| |
- |
| |
- | The <b>TransferHandler</b> is a class responsible for transfering data between components.
| |
- | The constructor takes a property name as a parameter.
| |
- |
| |
- | [[image: java_swing_simplednd.png | center]]
| |
- |
| |
- | == Icon drag & drop ==
| |
- |
| |
- | Some of the Java Swing components do not have built in drag support. <b>JLabel</b> component is such a component. We have to code the drag functionality ourselves.
| |
- |
| |
- | We will drag and drop icons. In the previous example, we used a text property. This time we will use an icon property.
| |
- |
| |
- | <source lang="java">
| |
- | import java.awt.FlowLayout;
| |
- | import java.awt.event.MouseAdapter;
| |
- | import java.awt.event.MouseEvent;
| |
- | import java.awt.event.MouseListener;
| |
- |
| |
- | import javax.swing.ImageIcon;
| |
- | import javax.swing.JButton;
| |
- | import javax.swing.JComponent;
| |
- | import javax.swing.JFrame;
| |
- | import javax.swing.JLabel;
| |
- | import javax.swing.JPanel;
| |
- | import javax.swing.TransferHandler;
| |
- |
| |
- |
| |
- | public class IconDnD extends JFrame {
| |
- |
| |
- |
| |
- | public IconDnD() {
| |
- |
| |
- | setTitle("Icon Drag & Drop");
| |
- |
| |
- | JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT, 50, 15));
| |
- |
| |
- | ImageIcon icon1 = new ImageIcon("sad.png");
| |
- | ImageIcon icon2 = new ImageIcon("plain.png");
| |
- | ImageIcon icon3 = new ImageIcon("crying.png");
| |
- |
| |
- | JButton button = new JButton(icon2);
| |
- | button.setFocusable(false);
| |
- |
| |
- | JLabel label1 = new JLabel(icon1, JLabel.CENTER);
| |
- | JLabel label2 = new JLabel(icon3, JLabel.CENTER);
| |
- |
| |
- | MouseListener listener = new DragMouseAdapter();
| |
- | label1.addMouseListener(listener);
| |
- | label2.addMouseListener(listener);
| |
- |
| |
- | label1.setTransferHandler(new TransferHandler("icon"));
| |
- | button.setTransferHandler(new TransferHandler("icon"));
| |
- | label2.setTransferHandler(new TransferHandler("icon"));
| |
- |
| |
- | panel.add(label1);
| |
- | panel.add(button);
| |
- | panel.add(label2);
| |
- | add(panel);
| |
- |
| |
- | pack();
| |
- | setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
| |
- | setLocationRelativeTo(null);
| |
- | setVisible(true);
| |
- | }
| |
- |
| |
- | class DragMouseAdapter extends MouseAdapter {
| |
- | public void mousePressed(MouseEvent e) {
| |
- | JComponent c = (JComponent) e.getSource();
| |
- | TransferHandler handler = c.getTransferHandler();
| |
- | handler.exportAsDrag(c, e, TransferHandler.COPY);
| |
- | }
| |
- | }
| |
- |
| |
- | public static void main(String[] args) {
| |
- | new IconDnD();
| |
- | }
| |
- | }
| |
- | </source>
| |
- |
| |
- | In the code example, we have two labels and a button. Each component displays an icon. The two labels enable drag
| |
- | gestures, the button accepts a drop gesture.
| |
- |
| |
- | <source lang="java">
| |
- | MouseListener listener = new DragMouseAdapter();
| |
- | label1.addMouseListener(listener);
| |
- | label2.addMouseListener(listener);
| |
- | </source>
| |
- |
| |
- | The drag support is not enabled by default for the label. We register a custom mouse adapter for both labels.
| |
- |
| |
- | <source lang="java">
| |
- | label1.setTransferHandler(new TransferHandler("icon"));
| |
- | button.setTransferHandler(new TransferHandler("icon"));
| |
- | label2.setTransferHandler(new TransferHandler("icon"));
| |
- | </source>
| |
- |
| |
- | Each of the three components has a <b>TransferHandler</b> class for an icon property.
| |
- | The <b>TransferHandler</b> is needed for both drag sources and drag targets as well.
| |
- |
| |
- |
| |
- | <source lang="java">
| |
- | JComponent c = (JComponent) e.getSource();
| |
- | TransferHandler handler = c.getTransferHandler();
| |
- | handler.exportAsDrag(c, e, TransferHandler.COPY);
| |
- | </source>
| |
- |
| |
- | These code lines initiate the drag support. We get the drag source. In our case it is a label instance.
| |
- | We get it's transfer handler object. And finally initiate the drag support with the <b>exportAsDrag()</b>
| |
- | method call.
| |
- |
| |
- | [[image: java_swing_icondnd.png | center]]
| |
- |
| |
- | == Custom JList drop example ==
| |
- |
| |
- | Some components do not have a default drop support. One of them is a JList component. There is a good reason for this.
| |
- | We don't know, if the data will be inserted into one row, or two or more rows. So we must implement manually the
| |
- | drop support for the list component.
| |
- |
| |
- | The comma separated text will be inserted into two or more rows. Text without a comma will go into one row.
| |
- |
| |
- | <source lang="java">
| |
- |
| |
- | import java.awt.Dimension;
| |
- | import java.awt.FlowLayout;
| |
- | import java.awt.datatransfer.DataFlavor;
| |
- | import java.awt.datatransfer.Transferable;
| |
- |
| |
- | import javax.swing.DefaultListModel;
| |
- | import javax.swing.DropMode;
| |
- | import javax.swing.JFrame;
| |
- | import javax.swing.JList;
| |
- | import javax.swing.JPanel;
| |
- | import javax.swing.JScrollPane;
| |
- | import javax.swing.JTextField;
| |
- | import javax.swing.ListSelectionModel;
| |
- | import javax.swing.TransferHandler;
| |
- |
| |
- |
| |
- | public class ListDrop extends JFrame {
| |
- |
| |
- | JTextField field;
| |
- | DefaultListModel model;
| |
- |
| |
- | public ListDrop() {
| |
- |
| |
- | setTitle("ListDrop");
| |
- |
| |
- | JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT, 15, 15));
| |
- |
| |
- | JScrollPane pane = new JScrollPane();
| |
- | pane.setPreferredSize(new Dimension(180, 150));
| |
- |
| |
- | model = new DefaultListModel();
| |
- | JList list = new JList(model);
| |
- |
| |
- | list.setDropMode(DropMode.INSERT);
| |
- | list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
| |
- | list.setTransferHandler(new ListHandler());
| |
- |
| |
- | field = new JTextField("");
| |
- | field.setPreferredSize(new Dimension(150, 25));
| |
- | field.setDragEnabled(true);
| |
- |
| |
- | panel.add(field);
| |
- | pane.getViewport().add(list);
| |
- | panel.add(pane);
| |
- |
| |
- | add(panel);
| |
- |
| |
- | pack();
| |
- |
| |
- | setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
| |
- | setLocationRelativeTo(null);
| |
- | setVisible(true);
| |
- | }
| |
- |
| |
- |
| |
- | private class ListHandler extends TransferHandler {
| |
- | public boolean canImport(TransferSupport support) {
| |
- | if (!support.isDrop()) {
| |
- | return false;
| |
- | }
| |
- |
| |
- | return support.isDataFlavorSupported(DataFlavor.stringFlavor);
| |
- | }
| |
- |
| |
- | public boolean importData(TransferSupport support) {
| |
- | if (!canImport(support)) {
| |
- | return false;
| |
- | }
| |
- |
| |
- | Transferable transferable = support.getTransferable();
| |
- | String line;
| |
- | try {
| |
- | line = (String) transferable.getTransferData(DataFlavor.stringFlavor);
| |
- | } catch (Exception e) {
| |
- | return false;
| |
- | }
| |
- |
| |
- | JList.DropLocation dl = (JList.DropLocation) support.getDropLocation();
| |
- | int index = dl.getIndex();
| |
- |
| |
- | String[] data = line.split(",");
| |
- | for (String item: data) {
| |
- | if (!item.isEmpty())
| |
- | model.add(index++, item.trim());
| |
- | }
| |
- | return true;
| |
- | }
| |
- | }
| |
- |
| |
- | public static void main(String[] args) {
| |
- | new ListDrop();
| |
- | }
| |
- | }
| |
- | </source>
| |
- |
| |
- | In the above example, we have a text field and a list component. The text in the text field can be dragged and
| |
- | dropped into the list. If the text is comma separated, the words will be split into rows. If not, the text will be
| |
- | inserted into one row.
| |
- |
| |
- | <source lang="java">
| |
- | list.setDropMode(DropMode.INSERT);
| |
- | </source>
| |
- |
| |
- | Here we specify a drop mode. The <b>DropMode.INSERT</b> specifies, that we are going to insert new items
| |
- | into the list component. If we chose <b>DropMode.INSERT</b>, we would drop new items onto the existing
| |
- | ones.
| |
- |
| |
- | <source lang="java">
| |
- | list.setTransferHandler(new ListHandler());
| |
- | </source>
| |
- |
| |
- | We set a custom transfer handler class.
| |
- |
| |
- | <source lang="java">
| |
- | field.setDragEnabled(true);
| |
- | </source>
| |
- |
| |
- | We enable the drag support for the text field component.
| |
- |
| |
- | <source lang="java">
| |
- | public boolean canImport(TransferSupport support) {
| |
- | if (!support.isDrop()) {
| |
- | return false;
| |
- | }
| |
- | return support.isDataFlavorSupported(DataFlavor.stringFlavor);
| |
- | }
| |
- | </source>
| |
- |
| |
- | This method tests suitability of a drop operation. Here we filter out the clipboard paste operations and
| |
- | allow only String drop operations. If the method returns false, the drop operation is cancelled.
| |
- |
| |
- | <source lang="java">
| |
- | public boolean importData(TransferSupport support) {
| |
- | ...
| |
- | }
| |
- | </source>
| |
- |
| |
- | The <b>importData()</b> method transfers the data from the clipboard or from the drag and drop operation to the drop location.
| |
- |
| |
- | <source lang="java">
| |
- | Transferable transferable = support.getTransferable();
| |
- | </source>
| |
- |
| |
- | The <b>Transferable</b> is the class, where the data is bundled.
| |
- |
| |
- | <source lang="java">
| |
- | line = (String) transferable.getTransferData(DataFlavor.stringFlavor);
| |
- | </source>
| |
- |
| |
- | We retrieve our data.
| |
- |
| |
- | <source lang="java">
| |
- | JList.DropLocation dl = (JList.DropLocation) support.getDropLocation();
| |
- | int index = dl.getIndex();
| |
- | </source>
| |
- |
| |
- | We get a drop location for the list. We retrieve the index, where the data will be inserted.
| |
- |
| |
- | <source lang="java">
| |
- | String[] data = line.split(",");
| |
- | for (String item: data) {
| |
- | if (!item.isEmpty())
| |
- | model.add(index++, item.trim());
| |
- | }
| |
- | </source>
| |
- |
| |
- | Here we split the text into parts and insert it into one or more rows.
| |
- |
| |
- | [[image: java_swing_listdrop.png | center]]
| |
- |
| |
- | The previous examples used components with built-in drag and drop support. Next we are going to create
| |
- | a drag and drop functionality from scratch.
| |
- |
| |
- | == Drag Gesture ==
| |
- |
| |
- | In the following example we will inspect a simple drag gesture. We will work with several classes needed to create
| |
- | a drag gesture. A <b>DragSource</b>, <b>DragGestureEvent</b>, <b>DragGestureListener</b>, <b>Transferable</b>.
| |
- |
| |
- | <source lang="java">
| |
- | import java.awt.Color;
| |
- | import java.awt.Cursor;
| |
- | import java.awt.Dimension;
| |
- | import java.awt.FlowLayout;
| |
- | import java.awt.datatransfer.DataFlavor;
| |
- | import java.awt.datatransfer.Transferable;
| |
- | import java.awt.dnd.DnDConstants;
| |
- | import java.awt.dnd.DragGestureEvent;
| |
- | import java.awt.dnd.DragGestureListener;
| |
- | import java.awt.dnd.DragSource;
| |
- |
| |
- | import javax.swing.JFrame;
| |
- | import javax.swing.JPanel;
| |
- |
| |
- |
| |
- | public class DragGesture extends JFrame implements
| |
- | DragGestureListener, Transferable {
| |
- |
| |
- | public DragGesture() {
| |
- |
| |
- | setTitle("Drag Gesture");
| |
- |
| |
- | JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT, 50, 15));
| |
- |
| |
- | JPanel left = new JPanel();
| |
- | left.setBackground(Color.red);
| |
- | left.setPreferredSize(new Dimension(120, 120));
| |
- |
| |
- | DragSource ds = new DragSource();
| |
- | ds.createDefaultDragGestureRecognizer(left,
| |
- | DnDConstants.ACTION_COPY, this);
| |
- |
| |
- | panel.add(left);
| |
- | add(panel);
| |
- |
| |
- | pack();
| |
- | setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
| |
- | setLocationRelativeTo(null);
| |
- | setVisible(true);
| |
- | }
| |
- |
| |
- | public void dragGestureRecognized(DragGestureEvent event) {
| |
- | System.out.println("grag gesture");
| |
- | Cursor cursor = null;
| |
- | if (event.getDragAction() == DnDConstants.ACTION_COPY) {
| |
- | cursor = DragSource.DefaultCopyDrop;
| |
- | }
| |
- | event.startDrag(cursor, this);
| |
- | }
| |
- |
| |
- | public static void main(String[] args) {
| |
- | new DragGesture();
| |
- | }
| |
- |
| |
- | public Object getTransferData(DataFlavor flavor) {
| |
- | return null;
| |
- | }
| |
- |
| |
- | public DataFlavor[] getTransferDataFlavors() {
| |
- | return new DataFlavor[0];
| |
- | }
| |
- |
| |
- | public boolean isDataFlavorSupported(DataFlavor flavor) {
| |
- | return false;
| |
- | }
| |
- | }
| |
- | </source>
| |
- |
| |
- | This simple example demostrates a drag gesture. The drag gesture is created, when we click on a component and move
| |
- | a mouse pointer, while the button is pressed. The example will show, how we can create a DragSource for a component.
| |
- |
| |
- | <source lang="java">
| |
- | public class DragGesture extends JFrame implements
| |
- | DragGestureListener, Transferable {
| |
- | </source>
| |
- |
| |
- | The DragGesture implements two interfaces. The <b>DragGestureListener</b> will listen for drag gestures.
| |
- | The <b>Transferable</b> handles data for a transfer operation. In the example, we will not
| |
- | transfer any data. We will only demonstrate a drag gesture. So the three necessary methods of the Transferable
| |
- | interface are left unimplemented.
| |
- |
| |
- | <source lang="java">
| |
- | DragSource ds = new DragSource();
| |
- | ds.createDefaultDragGestureRecognizer(left,
| |
- | DnDConstants.ACTION_COPY, this);
| |
- | </source>
| |
- |
| |
- | Here we create a <b>DragSource</b> object and register it for the left panel.
| |
- | The DragSource is the entity responsible for the initiation of the Drag and Drop operation.
| |
- | The <b>DragGestureListener</b> with a particular component.
| |
- |
| |
- | <source lang="java">
| |
- | public void dragGestureRecognized(DragGestureEvent event) {
| |
- |
| |
- | }
| |
- | </source>
| |
- |
| |
- | The <b>dragGestureRecognized()</b> method responds to a drag gesture.
| |
- |
| |
- | <source lang="java">
| |
- | Cursor cursor = null;
| |
- | if (event.getDragAction() == DnDConstants.ACTION_COPY) {
| |
- | cursor = DragSource.DefaultCopyDrop;
| |
- | }
| |
- | event.startDrag(cursor, this);
| |
- |
| |
- | </source>
| |
- |
| |
- | The <b>startDrag()</b> method of the DragGestureEvent finally starts the drag operation. We will specify two
| |
- | parameters. The cursor type and the Transferable object.
| |
- |
| |
- | <source lang="java">
| |
- | public Object getTransferData(DataFlavor flavor) {
| |
- | return null;
| |
- | }
| |
- |
| |
- | public DataFlavor[] getTransferDataFlavors() {
| |
- | return new DataFlavor[0];
| |
- | }
| |
- |
| |
- | public boolean isDataFlavorSupported(DataFlavor flavor) {
| |
- | return false;
| |
- | }
| |
- | </source>
| |
- |
| |
- | The object that implements the Transferable interface must implement these three methods. As I have already mentioned, we left these methods unimplemented for now.
| |
- |
| |
- | == A complex drag and drop example ==
| |
- |
| |
- | In the following example, we create a complex drag and drop example. We create a drag source a drop target and a transferable object.
| |
- |
| |
- | <source lang="java">
| |
- | import java.awt.Color;
| |
- | import java.awt.Cursor;
| |
- | import java.awt.Dimension;
| |
- | import java.awt.FlowLayout;
| |
- | import java.awt.datatransfer.DataFlavor;
| |
- | import java.awt.datatransfer.Transferable;
| |
- | import java.awt.datatransfer.UnsupportedFlavorException;
| |
- | import java.awt.dnd.DnDConstants;
| |
- | import java.awt.dnd.DragGestureEvent;
| |
- | import java.awt.dnd.DragGestureListener;
| |
- | import java.awt.dnd.DragSource;
| |
- | import java.awt.dnd.DropTarget;
| |
- | import java.awt.dnd.DropTargetAdapter;
| |
- | import java.awt.dnd.DropTargetDropEvent;
| |
- | import java.awt.event.ActionEvent;
| |
- | import java.awt.event.ActionListener;
| |
- |
| |
- | import javax.swing.JButton;
| |
- | import javax.swing.JColorChooser;
| |
- | import javax.swing.JFrame;
| |
- | import javax.swing.JPanel;
| |
- |
| |
- |
| |
- | public class ComplexExample extends JFrame
| |
- | implements DragGestureListener {
| |
- |
| |
- | JPanel panel;
| |
- | JPanel left;
| |
- |
| |
- | public ComplexExample() {
| |
- |
| |
- | setTitle("Complex Example");
| |
- |
| |
- | panel = new JPanel(new FlowLayout(FlowLayout.LEFT, 50, 15));
| |
- |
| |
- | JButton openb = new JButton("Choose Color");
| |
- | openb.setFocusable(false);
| |
- |
| |
- | left = new JPanel();
| |
- | left.setBackground(Color.red);
| |
- | left.setPreferredSize(new Dimension(100, 100));
| |
- |
| |
- | openb.addActionListener(new ActionListener() {
| |
- | public void actionPerformed(ActionEvent event) {
| |
- | JColorChooser clr = new JColorChooser();
| |
- | Color color = clr.showDialog(panel, "Choose Color", Color.white);
| |
- | left.setBackground(color);
| |
- | }
| |
- | });
| |
- |
| |
- | JPanel right = new JPanel();
| |
- | right.setBackground(Color.white);
| |
- | right.setPreferredSize(new Dimension(100, 100));
| |
- |
| |
- | new MyDropTargetListener(right);
| |
- |
| |
- | DragSource ds = new DragSource();
| |
- | ds.createDefaultDragGestureRecognizer(left,
| |
- | DnDConstants.ACTION_COPY, this);
| |
- |
| |
- | panel.add(openb);
| |
- | panel.add(left);
| |
- | panel.add(right);
| |
- | add(panel);
| |
- |
| |
- | pack();
| |
- | setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
| |
- | setLocationRelativeTo(null);
| |
- | setVisible(true);
| |
- | }
| |
- |
| |
- | public void dragGestureRecognized(DragGestureEvent event) {
| |
- | Cursor cursor = null;
| |
- | JPanel panel = (JPanel) event.getComponent();
| |
- |
| |
- | Color color = panel.getBackground();
| |
- |
| |
- | if (event.getDragAction() == DnDConstants.ACTION_COPY) {
| |
- | cursor = DragSource.DefaultCopyDrop;
| |
- | }
| |
- |
| |
- | event.startDrag(cursor, new TransferableColor(color));
| |
- | }
| |
- |
| |
- | class MyDropTargetListener extends DropTargetAdapter {
| |
- |
| |
- | private DropTarget dropTarget;
| |
- | private JPanel panel;
| |
- |
| |
- | public MyDropTargetListener(JPanel panel) {
| |
- | this.panel = panel;
| |
- |
| |
- | dropTarget = new DropTarget(panel, DnDConstants.ACTION_COPY,
| |
- | this, true, null);
| |
- | }
| |
- |
| |
- |
| |
- | public void drop(DropTargetDropEvent event) {
| |
- | try {
| |
- |
| |
- | Transferable tr = event.getTransferable();
| |
- | Color color = (Color) tr.getTransferData(TransferableColor.colorFlavor);
| |
- |
| |
- | if (event.isDataFlavorSupported(TransferableColor.colorFlavor)) {
| |
- |
| |
- | event.acceptDrop(DnDConstants.ACTION_COPY);
| |
- | this.panel.setBackground(color);
| |
- | event.dropComplete(true);
| |
- | return;
| |
- | }
| |
- | event.rejectDrop();
| |
- | } catch (Exception e) {
| |
- | e.printStackTrace();
| |
- | event.rejectDrop();
| |
- | }
| |
- | }
| |
- | }
| |
- |
| |
- | public static void main(String[] args) {
| |
- | new ComplexExample();
| |
- | }
| |
- | }
| |
- |
| |
- |
| |
- | class TransferableColor implements Transferable {
| |
- |
| |
- | protected static DataFlavor colorFlavor =
| |
- | new DataFlavor(Color.class, "A Color Object");
| |
- |
| |
- | protected static DataFlavor[] supportedFlavors = {
| |
- | colorFlavor,
| |
- | DataFlavor.stringFlavor,
| |
- | };
| |
- |
| |
- | Color color;
| |
- |
| |
- | public TransferableColor(Color color) { this.color = color; }
| |
- |
| |
- | public DataFlavor[] getTransferDataFlavors() { return supportedFlavors; }
| |
- |
| |
- | public boolean isDataFlavorSupported(DataFlavor flavor) {
| |
- | if (flavor.equals(colorFlavor) ||
| |
- | flavor.equals(DataFlavor.stringFlavor)) return true;
| |
- | return false;
| |
- | }
| |
- |
| |
- |
| |
- | public Object getTransferData(DataFlavor flavor)
| |
- | throws UnsupportedFlavorException
| |
- | {
| |
- | if (flavor.equals(colorFlavor))
| |
- | return color;
| |
- | else if (flavor.equals(DataFlavor.stringFlavor))
| |
- | return color.toString();
| |
- | else
| |
- | throw new UnsupportedFlavorException(flavor);
| |
- | }
| |
- | }
| |
- | </source>
| |
- |
| |
- | The code example shows a button and two panels. The button displays a color chooser dialog and sets a color
| |
- | for the first panel. The color can be dragged into the second panel.
| |
- |
| |
- | This example will enhance the previous one. We will add a drop target and a custom transferable object.
| |
- |
| |
- | <source lang="java">
| |
- | new MyDropTargetListener(right);
| |
- | </source>
| |
- |
| |
- | We register a drop target listener with the right panel.
| |
- |
| |
- | <source lang="java">
| |
- | event.startDrag(cursor, new TransferableColor(color));
| |
- | </source>
| |
- |
| |
- | The <b>Transferable</b> object.
| |
- |
| |
- | <source lang="java">
| |
- | public MyDropTargetListener(JPanel panel) {
| |
- | this.panel = panel;
| |
- |
| |
- | dropTarget = new DropTarget(panel, DnDConstants.ACTION_COPY,
| |
- | this, true, null);
| |
- | }
| |
- | </source>
| |
- |
| |
- | In the MyDropTargetListener we create a drop target object.
| |
- |
| |
- | <source lang="java">
| |
- | Transferable tr = event.getTransferable();
| |
- | Color color = (Color) tr.getTransferData(TransferableColor.colorFlavor);
| |
- |
| |
- | if (event.isDataFlavorSupported(TransferableColor.colorFlavor)) {
| |
- |
| |
- | event.acceptDrop(DnDConstants.ACTION_COPY);
| |
- | this.panel.setBackground(color);
| |
- | event.dropComplete(true);
| |
- | return;
| |
- | }
| |
- | </source>
| |
- |
| |
- | We get the data being transferred. In our case it is a color object. Here we set the color of the right panel.
| |
- |
| |
- | <source lang="java">
| |
- | event.rejectDrop();
| |
- | </source>
| |
- |
| |
- | If the conditions for a drag and drop operation are not fulfilled, we reject it.
| |
- |
| |
- | <source lang="java">
| |
- | protected static DataFlavor colorFlavor =
| |
- | new DataFlavor(Color.class, "A Color Object");
| |
- | </source>
| |
- |
| |
- | In the TransferableColor, we create a new <b>DataFlavor</b> object.
| |
- |
| |
- | <source lang="java">
| |
- |
| |
- | protected static DataFlavor[] supportedFlavors = {
| |
- | colorFlavor,
| |
- | DataFlavor.stringFlavor,
| |
- | };
| |
- | </source>
| |
- |
| |
- | Here we specify, what data flavors we support. In our case it is a custom defined color flavor and a pre-defined
| |
- | <b>DataFlavor.stringFlavor</b>.
| |
- |
| |
- | <source lang="java">
| |
- | public Object getTransferData(DataFlavor flavor)
| |
- | throws UnsupportedFlavorException
| |
- | {
| |
- | if (flavor.equals(colorFlavor))
| |
- | return color;
| |
- | else if (flavor.equals(DataFlavor.stringFlavor))
| |
- | return color.toString();
| |
- | else
| |
- | throw new UnsupportedFlavorException(flavor);
| |
- | }
| |
- | </source>
| |
- |
| |
- | Return an object for a specific data flavor.
| |
- |
| |
- | [[image: java_swing_complexexample.png | center]]
| |
- |
| |
- | [[Категория:Java]]
| |