Java Tutorial/Swing/Drag Drop — различия между версиями
Admin (обсуждение | вклад) м (1 версия) |
Admin (обсуждение | вклад) м (1 версия) |
(нет различий)
|
Текущая версия на 18:33, 31 мая 2010
Содержание
- 1 14. Basic drag and drop
- 2 14. Built-in drag and drop support: utilize a TransferHandler class
- 3 14. Choose Drop Action
- 4 14. Create a drag source a drop target and a transferable object.
- 5 14. Demonstrates how to add copy and drag support to a Swing component with TransferHandler
- 6 14. Demonstration of the top-level TransferHandler support on JFrame
- 7 14. Detect a drag initiating gesture in your application
- 8 14. DND Drag and drop List
- 9 14. Drag and drop between JList and JTextField
- 10 14. Drag and drop between JTextArea and JTextField
- 11 14. Drag-and-Drop customization: drag the foreground color from the first label and drop it as the background color into the second one
- 12 14. Drag and drop icons: use an icon property.
- 13 14. Drag-and-Drop Support for Images
- 14 14. Dragging and dropping text between a text area, a list, and a table
- 15 14. Dragging Text from a JLabel
- 16 14. DropMode.INSERT
- 17 14. DropMode.ON
- 18 14. DropMode.ON_OR_INSERT
- 19 14. Illustrates cut, copy, paste and drag and drop using three instances of JList
- 20 14. implements DragGestureListener, Transferable
- 21 14. JTable drag and drop
- 22 14. Location sensitive drag and drop
- 23 14. Making a Component Draggable
- 24 14. ScribblePane allows individual PolyLine lines to be selected, cut, copied, pasted, dragged, and dropped
- 25 14. Set tree drag mode to DropMode.INSERT
- 26 14. Set tree drag mode to DropMode.ON
- 27 14. Set tree drag mode to DropMode.ON_OR_INSERT
- 28 14. Set tree DropMode to DropMode.USE_SELECTION
- 29 14. Transfer both Text and Color between JTextField and JTextArea
- 30 14. Various drop actions
14. Basic drag and drop
<source lang="java">
/*
* Copyright (c) 1995 - 2008 Sun Microsystems, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * - Neither the name of Sun Microsystems nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
/*
* BasicDnD.java requires no other files. */
import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.StringSelection; import java.awt.datatransfer.Transferable; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.BorderFactory; import javax.swing.BoxLayout; import javax.swing.DefaultListModel; import javax.swing.DropMode; import javax.swing.JCheckBox; import javax.swing.JColorChooser; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JList; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.JTable; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.JTree; import javax.swing.ListSelectionModel; import javax.swing.SwingUtilities; import javax.swing.TransferHandler; import javax.swing.UIManager; import javax.swing.table.DefaultTableModel; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreeSelectionModel; public class BasicDnD extends JPanel implements ActionListener {
private static JFrame frame; private JTextArea textArea; private JTextField textField; private JList list; private JTable table; private JTree tree; private JColorChooser colorChooser; private JCheckBox toggleDnD; public BasicDnD() { super(new BorderLayout()); JPanel leftPanel = createVerticalBoxPanel(); JPanel rightPanel = createVerticalBoxPanel(); // Create a table model. DefaultTableModel tm = new DefaultTableModel(); tm.addColumn("Column 0"); tm.addColumn("Column 1"); tm.addColumn("Column 2"); tm.addColumn("Column 3"); tm.addRow(new String[] { "Table 00", "Table 01", "Table 02", "Table 03" }); tm.addRow(new String[] { "Table 10", "Table 11", "Table 12", "Table 13" }); tm.addRow(new String[] { "Table 20", "Table 21", "Table 22", "Table 23" }); tm.addRow(new String[] { "Table 30", "Table 31", "Table 32", "Table 33" }); // LEFT COLUMN // Use the table model to create a table. table = new JTable(tm); leftPanel.add(createPanelForComponent(table, "JTable")); // Create a color chooser. colorChooser = new JColorChooser(); leftPanel.add(createPanelForComponent(colorChooser, "JColorChooser")); // RIGHT COLUMN // Create a textfield. textField = new JTextField(30); textField.setText("Favorite foods:\nPizza, Moussaka, Pot roast"); rightPanel.add(createPanelForComponent(textField, "JTextField")); // Create a scrolled text area. textArea = new JTextArea(5, 30); textArea.setText("Favorite shows:\nBuffy, Alias, Angel"); JScrollPane scrollPane = new JScrollPane(textArea); rightPanel.add(createPanelForComponent(scrollPane, "JTextArea")); // Create a list model and a list. DefaultListModel listModel = new DefaultListModel(); listModel.addElement("Martha Washington"); listModel.addElement("Abigail Adams"); listModel.addElement("Martha Randolph"); listModel.addElement("Dolley Madison"); listModel.addElement("Elizabeth Monroe"); listModel.addElement("Louisa Adams"); listModel.addElement("Emily Donelson"); list = new JList(listModel); list.setVisibleRowCount(-1); list.getSelectionModel().setSelectionMode( ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); list.setTransferHandler(new TransferHandler() { public boolean canImport(TransferHandler.TransferSupport info) { // we only import Strings if (!info.isDataFlavorSupported(DataFlavor.stringFlavor)) { return false; } JList.DropLocation dl = (JList.DropLocation) info.getDropLocation(); if (dl.getIndex() == -1) { return false; } return true; } public boolean importData(TransferHandler.TransferSupport info) { if (!info.isDrop()) { return false; } // Check for String flavor if (!info.isDataFlavorSupported(DataFlavor.stringFlavor)) { displayDropLocation("List doesn"t accept a drop of this type."); return false; } JList.DropLocation dl = (JList.DropLocation) info.getDropLocation(); DefaultListModel listModel = (DefaultListModel) list.getModel(); int index = dl.getIndex(); boolean insert = dl.isInsert(); // Get the current string under the drop. String value = (String) listModel.getElementAt(index); // Get the string that is being dropped. Transferable t = info.getTransferable(); String data; try { data = (String) t.getTransferData(DataFlavor.stringFlavor); } catch (Exception e) { return false; } // Display a dialog with the drop information. String dropValue = "\"" + data + "\" dropped "; if (dl.isInsert()) { if (dl.getIndex() == 0) { displayDropLocation(dropValue + "at beginning of list"); } else if (dl.getIndex() >= list.getModel().getSize()) { displayDropLocation(dropValue + "at end of list"); } else { String value1 = (String) list.getModel().getElementAt( dl.getIndex() - 1); String value2 = (String) list.getModel() .getElementAt(dl.getIndex()); displayDropLocation(dropValue + "between \"" + value1 + "\" and \"" + value2 + "\""); } } else { displayDropLocation(dropValue + "on top of " + "\"" + value + "\""); } /** * This is commented out for the basicdemo.html tutorial page. * If you * add this code snippet back and delete the * "return false;" line, the * list will accept drops * of type string. // Perform the actual * import. if (insert) { listModel.add(index, data); } else { * listModel.set(index, data); } return true; */ return false; } public int getSourceActions(JComponent c) { return COPY; } protected Transferable createTransferable(JComponent c) { JList list = (JList) c; Object[] values = list.getSelectedValues(); StringBuffer buff = new StringBuffer(); for (int i = 0; i < values.length; i++) { Object val = values[i]; buff.append(val == null ? "" : val.toString()); if (i != values.length - 1) { buff.append("\n"); } } return new StringSelection(buff.toString()); } }); list.setDropMode(DropMode.ON_OR_INSERT); JScrollPane listView = new JScrollPane(list); listView.setPreferredSize(new Dimension(300, 100)); rightPanel.add(createPanelForComponent(listView, "JList")); // Create a tree. DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode("Mia Familia"); DefaultMutableTreeNode sharon = new DefaultMutableTreeNode("Sharon"); rootNode.add(sharon); DefaultMutableTreeNode maya = new DefaultMutableTreeNode("Maya"); sharon.add(maya); DefaultMutableTreeNode anya = new DefaultMutableTreeNode("Anya"); sharon.add(anya); sharon.add(new DefaultMutableTreeNode("Bongo")); maya.add(new DefaultMutableTreeNode("Muffin")); anya.add(new DefaultMutableTreeNode("Winky")); DefaultTreeModel model = new DefaultTreeModel(rootNode); tree = new JTree(model); tree.getSelectionModel().setSelectionMode( TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION); JScrollPane treeView = new JScrollPane(tree); treeView.setPreferredSize(new Dimension(300, 100)); rightPanel.add(createPanelForComponent(treeView, "JTree")); // Create the toggle button. toggleDnD = new JCheckBox("Turn on Drag and Drop"); toggleDnD.setActionCommand("toggleDnD"); toggleDnD.addActionListener(this); JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftPanel, rightPanel); splitPane.setOneTouchExpandable(true); add(splitPane, BorderLayout.CENTER); add(toggleDnD, BorderLayout.PAGE_END); setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); } protected JPanel createVerticalBoxPanel() { JPanel p = new JPanel(); p.setLayout(new BoxLayout(p, BoxLayout.PAGE_AXIS)); p.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); return p; } public JPanel createPanelForComponent(JComponent comp, String title) { JPanel panel = new JPanel(new BorderLayout()); panel.add(comp, BorderLayout.CENTER); if (title != null) { panel.setBorder(BorderFactory.createTitledBorder(title)); } return panel; } private void displayDropLocation(final String string) { SwingUtilities.invokeLater(new Runnable() { public void run() { JOptionPane.showMessageDialog(null, string); } }); } public void actionPerformed(ActionEvent e) { if ("toggleDnD".equals(e.getActionCommand())) { boolean toggle = toggleDnD.isSelected(); textArea.setDragEnabled(toggle); textField.setDragEnabled(toggle); list.setDragEnabled(toggle); table.setDragEnabled(toggle); tree.setDragEnabled(toggle); colorChooser.setDragEnabled(toggle); } } /** * Create the GUI and show it. For thread safety, this method should be * invoked from the event-dispatching thread. */ private static void createAndShowGUI() { // Create and set up the window. frame = new JFrame("BasicDnD"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // Create and set up the content pane. JComponent newContentPane = new BasicDnD(); newContentPane.setOpaque(true); // content panes must be opaque frame.setContentPane(newContentPane); // Display the window. frame.pack(); frame.setVisible(true); } public static void main(String[] args) { // Schedule a job for the event-dispatching thread: // creating and showing this application"s GUI. javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { // Turn off metal"s use of bold fonts UIManager.put("swing.boldMetal", Boolean.FALSE); createAndShowGUI(); } }); }
}</source>
14. Built-in drag and drop support: utilize a TransferHandler class
<source lang="java">
import java.awt.FlowLayout; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JTextField; import javax.swing.TransferHandler; public class SimpleDnD {
public static void main(String[] args) { JTextField field = new JTextField(10); JButton button = new JButton("Button"); JFrame f = new JFrame(); f.setTitle("Simple Drag & Drop"); f.setLayout(new FlowLayout()); f.add(button); f.add(field); field.setDragEnabled(true); button.setTransferHandler(new TransferHandler("text")); f.setSize(330, 150); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.setLocationRelativeTo(null); f.setVisible(true); }
}</source>
14. Choose Drop Action
<source lang="java">
/*
* Copyright (c) 1995 - 2008 Sun Microsystems, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * - Neither the name of Sun Microsystems nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.Rectangle; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.StringSelection; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import javax.swing.BorderFactory; import javax.swing.BoxLayout; import javax.swing.DefaultListModel; import javax.swing.DropMode; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.ListSelectionModel; import javax.swing.SwingUtilities; import javax.swing.TransferHandler; import javax.swing.UIManager; public class ChooseDropActionDemo extends JFrame {
DefaultListModel from = new DefaultListModel(); DefaultListModel copy = new DefaultListModel(); DefaultListModel move = new DefaultListModel(); JList dragFrom; public ChooseDropActionDemo() { super("ChooseDropActionDemo"); for (int i = 15; i >= 0; i--) { from.add(0, "Source item " + i); } for (int i = 2; i >= 0; i--) { copy.add(0, "Target item " + i); move.add(0, "Target item " + i); } JPanel p = new JPanel(); p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS)); dragFrom = new JList(from); dragFrom.setTransferHandler(new FromTransferHandler()); dragFrom.setPrototypeCellValue("List Item WWWWWW"); dragFrom.setDragEnabled(true); dragFrom.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); JLabel label = new JLabel("Drag from here:"); label.setAlignmentX(0f); p.add(label); JScrollPane sp = new JScrollPane(dragFrom); sp.setAlignmentX(0f); p.add(sp); add(p, BorderLayout.WEST); JList moveTo = new JList(move); moveTo.setTransferHandler(new ToTransferHandler(TransferHandler.COPY)); moveTo.setDropMode(DropMode.INSERT); JList copyTo = new JList(copy); copyTo.setTransferHandler(new ToTransferHandler(TransferHandler.MOVE)); copyTo.setDropMode(DropMode.INSERT); p = new JPanel(); p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS)); label = new JLabel("Drop to COPY to here:"); ; label.setAlignmentX(0f); p.add(label); sp = new JScrollPane(moveTo); sp.setAlignmentX(0f); p.add(sp); label = new JLabel("Drop to MOVE to here:"); label.setAlignmentX(0f); p.add(label); sp = new JScrollPane(copyTo); sp.setAlignmentX(0f); p.add(sp); p.setBorder(BorderFactory.createEmptyBorder(0, 2, 0, 0)); add(p, BorderLayout.CENTER); ((JPanel) getContentPane()).setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2)); getContentPane().setPreferredSize(new Dimension(320, 315)); } private static void createAndShowGUI() { // Create and set up the window. ChooseDropActionDemo test = new ChooseDropActionDemo(); test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // Display the window. test.pack(); test.setVisible(true); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { // Turn off metal"s use of bold fonts UIManager.put("swing.boldMetal", Boolean.FALSE); createAndShowGUI(); } }); } class FromTransferHandler extends TransferHandler { public int getSourceActions(JComponent comp) { return COPY_OR_MOVE; } private int index = 0; public Transferable createTransferable(JComponent comp) { index = dragFrom.getSelectedIndex(); if (index < 0 || index >= from.getSize()) { return null; } return new StringSelection((String) dragFrom.getSelectedValue()); } public void exportDone(JComponent comp, Transferable trans, int action) { if (action != MOVE) { return; } from.removeElementAt(index); } } class ToTransferHandler extends TransferHandler { int action; public ToTransferHandler(int action) { this.action = action; } public boolean canImport(TransferHandler.TransferSupport support) { // for the demo, we"ll only support drops (not clipboard paste) if (!support.isDrop()) { return false; } // we only import Strings if (!support.isDataFlavorSupported(DataFlavor.stringFlavor)) { return false; } boolean actionSupported = (action & support.getSourceDropActions()) == action; if (actionSupported) { support.setDropAction(action); return true; } return false; } public boolean importData(TransferHandler.TransferSupport support) { // if we can"t handle the import, say so if (!canImport(support)) { return false; } // fetch the drop location JList.DropLocation dl = (JList.DropLocation) support.getDropLocation(); int index = dl.getIndex(); // fetch the data and bail if this fails String data; try { data = (String) support.getTransferable().getTransferData( DataFlavor.stringFlavor); } catch (UnsupportedFlavorException e) { return false; } catch (java.io.IOException e) { return false; } JList list = (JList) support.getComponent(); DefaultListModel model = (DefaultListModel) list.getModel(); model.insertElementAt(data, index); Rectangle rect = list.getCellBounds(index, index); list.scrollRectToVisible(rect); list.setSelectedIndex(index); list.requestFocusInWindow(); return true; } }
}</source>
14. 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 javax.swing.JFrame; import javax.swing.JPanel; public class ComplexExample extends JFrame implements DragGestureListener {
public ComplexExample() { JPanel left = new JPanel(); left.setBackground(Color.red); JPanel right = new JPanel(); right.setBackground(Color.white); new MyDropTargetListener(right); DragSource ds = new DragSource(); ds.createDefaultDragGestureRecognizer(left, DnDConstants.ACTION_COPY, this); setLayout(new FlowLayout()); add(left); add(right); setSize(40,50); 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 }; 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>
14. Demonstrates how to add copy and drag support to a Swing component with TransferHandler
<source lang="java">
/*
* Copyright (c) 2004 David Flanagan. All rights reserved. * This code is from the book Java Examples in a Nutshell, 3nd Edition. * It is provided AS-IS, WITHOUT ANY WARRANTY either expressed or implied. * You may study, use, and modify it for any non-commercial purpose, * including teaching and use in open-source projects. * You may distribute it non-commercially as long as you retain this notice. * For a commercial use license, or to purchase the book, * please visit http://www.davidflanagan.ru/javaexamples3. */
import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionAdapter; import java.text.DateFormat; import java.util.Date; import javax.swing.ActionMap; import javax.swing.InputMap; import javax.swing.JLabel; import javax.swing.KeyStroke; import javax.swing.Timer; import javax.swing.TransferHandler; import javax.swing.border.LineBorder; /**
* A custom Swing component that displays a simple digital clock. Demonstrates * how to add copy and drag support to a Swing component with TransferHandler. */
public class DigitalClock extends JLabel {
DateFormat format; // How to display the time in string form int updateFrequency; // How often to update the time (in milliseconds) Timer timer; // Triggers repeated updates to the clock public DigitalClock() { // Set default values for our properties setFormat(DateFormat.getTimeInstance(DateFormat.MEDIUM, getLocale())); setUpdateFrequency(1000); // Update once a second // Specify a Swing TransferHandler object to do the dirty work of // copy-and-paste and drag-and-drop for us. This one will transfer // the value of the "time" property. Since this property is read-only // it will allow drags but not drops. setTransferHandler(new TransferHandler("time")); // Since JLabel does not normally support drag-and-drop, we need an // event handler to detect a drag and start the transfer. addMouseMotionListener(new MouseMotionAdapter() { public void mouseDragged(MouseEvent e) { getTransferHandler().exportAsDrag(DigitalClock.this, e, TransferHandler.COPY); } }); // Before we can have a keyboard binding for a Copy command, // the component needs to be able to accept keyboard focus. setFocusable(true); // Request focus when we"re clicked on addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent e) { requestFocus(); } }); // Use a LineBorder to indicate when we"ve got the keyboard focus addFocusListener(new FocusListener() { public void focusGained(FocusEvent e) { setBorder(LineBorder.createBlackLineBorder()); } public void focusLost(FocusEvent e) { setBorder(null); } }); // Now bind the Ctrl-C keystroke to a "Copy" command. InputMap im = new InputMap(); im.setParent(getInputMap(WHEN_FOCUSED)); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.CTRL_MASK), "Copy"); setInputMap(WHEN_FOCUSED, im); // And bind the "Copy" command to a pre-defined Action that performs // a copy using the TransferHandler we"ve installed. ActionMap am = new ActionMap(); am.setParent(getActionMap()); am.put("Copy", TransferHandler.getCopyAction()); setActionMap(am); // Create a javax.swing.Timer object that will generate ActionEvents // to tell us when to update the displayed time. Every updateFrequency // milliseconds, this timer will cause the actionPerformed() method // to be invoked. (For non-GUI applications, see java.util.Timer.) timer = new Timer(updateFrequency, new ActionListener() { public void actionPerformed(ActionEvent e) { setText(getTime()); // set label to current time string } }); timer.setInitialDelay(0); // Do the first update immediately timer.start(); // Start timing now! } // Return the current time as a String. // This is the property accessor method used by the TransferHandler. // Since there is a getter, but no setter, the TransferHandler will // reject any attempts to drop data on us. public String getTime() { // Use the DateFormat object to convert current time to a string return format.format(new Date()); } // Here are two related property setter methods public void setFormat(DateFormat format) { this.format = format; } public void setUpdateFrequency(int ms) { this.updateFrequency = ms; }
}</source>
14. Demonstration of the top-level TransferHandler support on JFrame
<source lang="java">
/*
* Copyright (c) 1995 - 2008 Sun Microsystems, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * - Neither the name of Sun Microsystems nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
import javax.swing.*; import javax.swing.event.*; import java.awt.*; import java.awt.event.*; import java.io.*; import java.net.*; import java.awt.datatransfer.*; import java.awt.dnd.*; import java.util.*; /**
* Demonstration of the top-level {@code TransferHandler} * support on {@code JFrame}. * * @author Shannon Hickey */
public class TopLevelTransferHandlerDemo extends JFrame {
private static boolean DEMO = false; private JDesktopPane dp = new JDesktopPane(); private DefaultListModel listModel = new DefaultListModel(); private JList list = new JList(listModel); private static int left; private static int top; private JCheckBoxMenuItem copyItem; private JCheckBoxMenuItem nullItem; private JCheckBoxMenuItem thItem; private class Doc extends InternalFrameAdapter implements ActionListener { String name; JInternalFrame frame; TransferHandler th; JTextArea area; public Doc(File file) { this.name = file.getName(); try { init(file.toURI().toURL()); } catch (MalformedURLException e) { e.printStackTrace(); } } public Doc(String name) { this.name = name; init(getClass().getResource(name)); } private void init(URL url) { frame = new JInternalFrame(name); frame.addInternalFrameListener(this); listModel.add(listModel.size(), this); area = new JTextArea(); area.setMargin(new Insets(5, 5, 5, 5)); try { BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream())); String in; while ((in = reader.readLine()) != null) { area.append(in); area.append("\n"); } reader.close(); } catch (Exception e) { e.printStackTrace(); return; } th = area.getTransferHandler(); area.setFont(new Font("monospaced", Font.PLAIN, 12)); area.setCaretPosition(0); area.setDragEnabled(true); area.setDropMode(DropMode.INSERT); frame.getContentPane().add(new JScrollPane(area)); dp.add(frame); frame.show(); if (DEMO) { frame.setSize(300, 200); } else { frame.setSize(400, 300); } frame.setResizable(true); frame.setClosable(true); frame.setIconifiable(true); frame.setMaximizable(true); frame.setLocation(left, top); incr(); SwingUtilities.invokeLater(new Runnable() { public void run() { select(); } }); nullItem.addActionListener(this); setNullTH(); } public void internalFrameClosing(InternalFrameEvent event) { listModel.removeElement(this); nullItem.removeActionListener(this); } public void internalFrameOpened(InternalFrameEvent event) { int index = listModel.indexOf(this); list.getSelectionModel().setSelectionInterval(index, index); } public void internalFrameActivated(InternalFrameEvent event) { int index = listModel.indexOf(this); list.getSelectionModel().setSelectionInterval(index, index); } public String toString() { return name; } public void select() { try { frame.toFront(); frame.setSelected(true); } catch (java.beans.PropertyVetoException e) {} } public void actionPerformed(ActionEvent ae) { setNullTH(); } public void setNullTH() { if (nullItem.isSelected()) { area.setTransferHandler(null); } else { area.setTransferHandler(th); } } } private TransferHandler handler = new TransferHandler() { public boolean canImport(TransferHandler.TransferSupport support) { if (!support.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) { return false; } if (copyItem.isSelected()) { boolean copySupported = (COPY & support.getSourceDropActions()) == COPY; if (!copySupported) { return false; } support.setDropAction(COPY); } return true; } public boolean importData(TransferHandler.TransferSupport support) { if (!canImport(support)) { return false; } Transferable t = support.getTransferable(); try { java.util.List<File> l = (java.util.List<File>)t.getTransferData(DataFlavor.javaFileListFlavor); for (File f : l) { new Doc(f); } } catch (UnsupportedFlavorException e) { return false; } catch (IOException e) { return false; } return true; } }; private static void incr() { left += 30; top += 30; if (top == 150) { top = 0; } } public TopLevelTransferHandlerDemo() { super("TopLevelTransferHandlerDemo"); setJMenuBar(createDummyMenuBar()); getContentPane().add(createDummyToolBar(), BorderLayout.NORTH); JSplitPane sp = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, list, dp); sp.setDividerLocation(120); getContentPane().add(sp); //new Doc("sample.txt"); //new Doc("sample.txt"); //new Doc("sample.txt"); list.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION); list.addListSelectionListener(new ListSelectionListener() { public void valueChanged(ListSelectionEvent e) { if (e.getValueIsAdjusting()) { return; } Doc val = (Doc)list.getSelectedValue(); if (val != null) { val.select(); } } }); final TransferHandler th = list.getTransferHandler(); nullItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { if (nullItem.isSelected()) { list.setTransferHandler(null); } else { list.setTransferHandler(th); } } }); thItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { if (thItem.isSelected()) { setTransferHandler(handler); } else { setTransferHandler(null); } } }); dp.setTransferHandler(handler); } private static void createAndShowGUI(String[] args) { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (Exception e) { } TopLevelTransferHandlerDemo test = new TopLevelTransferHandlerDemo(); test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); if (DEMO) { test.setSize(493, 307); } else { test.setSize(800, 600); } test.setLocationRelativeTo(null); test.setVisible(true); test.list.requestFocus(); } public static void main(final String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { //Turn off metal"s use of bold fonts UIManager.put("swing.boldMetal", Boolean.FALSE); createAndShowGUI(args); } }); } private JToolBar createDummyToolBar() { JToolBar tb = new JToolBar(); JButton b; b = new JButton("New"); b.setRequestFocusEnabled(false); tb.add(b); b = new JButton("Open"); b.setRequestFocusEnabled(false); tb.add(b); b = new JButton("Save"); b.setRequestFocusEnabled(false); tb.add(b); b = new JButton("Print"); b.setRequestFocusEnabled(false); tb.add(b); b = new JButton("Preview"); b.setRequestFocusEnabled(false); tb.add(b); tb.setFloatable(false); return tb; } private JMenuBar createDummyMenuBar() { JMenuBar mb = new JMenuBar(); mb.add(createDummyMenu("File")); mb.add(createDummyMenu("Edit")); mb.add(createDummyMenu("Search")); mb.add(createDummyMenu("View")); mb.add(createDummyMenu("Tools")); mb.add(createDummyMenu("Help")); JMenu demo = new JMenu("Demo"); demo.setMnemonic(KeyEvent.VK_D); mb.add(demo); thItem = new JCheckBoxMenuItem("Use Top-Level TransferHandler"); thItem.setMnemonic(KeyEvent.VK_T); demo.add(thItem); nullItem = new JCheckBoxMenuItem("Remove TransferHandler from List and Text"); nullItem.setMnemonic(KeyEvent.VK_R); demo.add(nullItem); copyItem = new JCheckBoxMenuItem("Use COPY Action"); copyItem.setMnemonic(KeyEvent.VK_C); demo.add(copyItem); return mb; } private JMenu createDummyMenu(String str) { JMenu menu = new JMenu(str); JMenuItem item = new JMenuItem("[Empty]"); item.setEnabled(false); menu.add(item); return menu; }
}</source>
14. Detect a drag initiating gesture in your application
<source lang="java">
import java.awt.BorderLayout; import java.awt.dnd.DnDConstants; import java.awt.dnd.DragGestureEvent; import java.awt.dnd.DragGestureListener; import java.awt.dnd.DragGestureRecognizer; import java.awt.dnd.DragSource; import javax.swing.JFrame; import javax.swing.JList; import javax.swing.JScrollPane; import javax.swing.ListSelectionModel; public class Main extends JFrame implements DragGestureListener {
String[] items = { "Java", "C", "C++", "Lisp", "Perl", "Python" }; DragSource ds = new DragSource(); JList jl = new JList(items); public Main() { setSize(200, 150); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); jl.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); getContentPane().add(new JScrollPane(jl), BorderLayout.CENTER); DragGestureRecognizer dgr = ds.createDefaultDragGestureRecognizer(jl, DnDConstants.ACTION_COPY, this); setVisible(true); } public void dragGestureRecognized(DragGestureEvent dge) { System.out.println("Drag Gesture Recognized!"); } public static void main(String args[]) { new Main(); }
}</source>
14. DND Drag and drop List
<source lang="java">
/**
* This is an example of a component, which serves as a DragSource as * well as Drop Target. * To illustrate the concept, JList has been used as a droppable target * and a draggable source. * Any component can be used instead of a JList. * The code also contains debugging messages which can be used for * diagnostics and understanding the flow of events. * * @version 1.0 */
import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.StringSelection; 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 java.awt.dnd.DragSourceDragEvent; import java.awt.dnd.DragSourceDropEvent; import java.awt.dnd.DragSourceEvent; import java.awt.dnd.DragSourceListener; import java.awt.dnd.DropTarget; import java.awt.dnd.DropTargetDragEvent; import java.awt.dnd.DropTargetDropEvent; import java.awt.dnd.DropTargetEvent; import java.awt.dnd.DropTargetListener; import javax.swing.DefaultListModel; import javax.swing.JList; import javax.swing.ListModel;
public class DNDList extends JList implements DropTargetListener, DragSourceListener, DragGestureListener {
/** * enables this component to be a dropTarget */ DropTarget dropTarget = null; /** * enables this component to be a Drag Source */ DragSource dragSource = null; /** * constructor - initializes the DropTarget and DragSource. */ public DNDList( ListModel dataModel ) { super( dataModel ); dropTarget = new DropTarget( this, this ); dragSource = new DragSource(); dragSource.createDefaultDragGestureRecognizer( this, DnDConstants.ACTION_MOVE, this ); } /** * is invoked when you are dragging over the DropSite * */ public void dragEnter( DropTargetDragEvent event ) { // debug messages for diagnostics System.out.println( "dragEnter" ); event.acceptDrag( DnDConstants.ACTION_MOVE ); } /** * is invoked when you are exit the DropSite without dropping * */ public void dragExit( DropTargetEvent event ) { System.out.println( "dragExit" ); } /** * is invoked when a drag operation is going on * */ public void dragOver( DropTargetDragEvent event ) { System.out.println( "dragOver" ); } /** * a drop has occurred * */ public void drop( DropTargetDropEvent event ) { try { Transferable transferable = event.getTransferable(); // we accept only Strings if( transferable.isDataFlavorSupported( DataFlavor.stringFlavor ) ) { event.acceptDrop( DnDConstants.ACTION_MOVE ); String s = ( String )transferable.getTransferData( DataFlavor.stringFlavor ); addElement( s ); event.getDropTargetContext().dropComplete( true ); } else { event.rejectDrop(); } } catch( Exception exception ) { System.err.println( "Exception" + exception.getMessage() ); event.rejectDrop(); } } /** * is invoked if the use modifies the current drop gesture * */ public void dropActionChanged( DropTargetDragEvent event ) { } /** * a drag gesture has been initiated * */ public void dragGestureRecognized( DragGestureEvent event ) { Object selected = getSelectedValue(); if( selected != null ) { StringSelection text = new StringSelection( selected.toString() ); // as the name suggests, starts the dragging dragSource.startDrag( event, DragSource.DefaultMoveDrop, text, this ); } else { System.out.println( "nothing was selected" ); } } /** * this message goes to DragSourceListener, informing it that the dragging * has ended * */ public void dragDropEnd( DragSourceDropEvent event ) { if( event.getDropSuccess() ) { removeElement(); } } /** * this message goes to DragSourceListener, informing it that the dragging * has entered the DropSite * */ public void dragEnter( DragSourceDragEvent event ) { System.out.println( " dragEnter" ); } /** * this message goes to DragSourceListener, informing it that the dragging * has exited the DropSite * */ public void dragExit( DragSourceEvent event ) { System.out.println( "dragExit" ); } /** * this message goes to DragSourceListener, informing it that the dragging is * currently ocurring over the DropSite * */ public void dragOver( DragSourceDragEvent event ) { System.out.println( "dragExit" ); } /** * is invoked when the user changes the dropAction * */ public void dropActionChanged( DragSourceDragEvent event ) { System.out.println( "dropActionChanged" ); } /** * adds elements to itself * */ public void addElement( Object s ) { ( ( DefaultListModel )getModel() ).addElement( s.toString() ); } /** * removes an element from itself */ public void removeElement() { ( ( DefaultListModel )getModel() ).removeElement( getSelectedValue() ); }
}</source>
14. Drag and drop between JList and JTextField
<source lang="java">
import java.awt.BorderLayout; import java.awt.Rectangle; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import javax.swing.DefaultListModel; import javax.swing.DropMode; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextField; import javax.swing.TransferHandler; public class DnDDemo3 {
public static void main(String[] args) { JPanel north = new JPanel(); north.add(new JLabel("Drag from here:")); JTextField field = new JTextField(10); field.setDragEnabled(true); north.add(field); final DefaultListModel listModel = new DefaultListModel(); listModel.addElement("first"); listModel.addElement("second"); final JList list = new JList(listModel); list.setDragEnabled(true); list.setTransferHandler(new TransferHandler() { public boolean canImport(TransferHandler.TransferSupport support) { if (!support.isDataFlavorSupported(DataFlavor.stringFlavor)) { return false; } JList.DropLocation dl = (JList.DropLocation) support.getDropLocation(); if (dl.getIndex() == -1) { return false; } else { return true; } } public boolean importData(TransferHandler.TransferSupport support) { if (!canImport(support)) { return false; } Transferable transferable = support.getTransferable(); String data; try { data = (String) transferable.getTransferData(DataFlavor.stringFlavor); } catch (Exception e) { return false; } JList.DropLocation dl = (JList.DropLocation) support.getDropLocation(); int index = dl.getIndex(); if (dl.isInsert()) { listModel.add(index, data); } else { listModel.set(index, data); } Rectangle r = list.getCellBounds(index, index); list.scrollRectToVisible(r); return true; } }); JScrollPane center = new JScrollPane(); center.setViewportView(list); list.setDropMode(DropMode.USE_SELECTION); JPanel cp = new JPanel(); cp.setLayout(new BorderLayout()); cp.add(north, BorderLayout.NORTH); cp.add(center, BorderLayout.CENTER); JFrame frame = new JFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setContentPane(cp); frame.pack(); frame.setVisible(true); }
}</source>
14. Drag and drop between JTextArea and JTextField
<source lang="java">
import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.JTextField; public class DnDBetweenJTextAreaAndJTextFieldDemo {
public static void main(String[] args) { JFrame frame = new JFrame("Drag and Drop Demo"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setContentPane(new JPanel()); JTextField textField = new JTextField(25); textField.setText("www.jexp.ru"); frame.add(textField); JTextArea textArea = new JTextArea(4, 25); textArea.setText("Demonstrating\ndrag and drop"); frame.getContentPane().add(new JScrollPane(textArea)); textArea.setDragEnabled(true); textField.setDragEnabled(true); frame.pack(); frame.setVisible(true); }
}</source>
14. Drag-and-Drop customization: drag the foreground color from the first label and drop it as the background color into the second one
<source lang="java">
/*
* Copyright (c) 2004 David Flanagan. All rights reserved. * This code is from the book Java Examples in a Nutshell, 3nd Edition. * It is provided AS-IS, WITHOUT ANY WARRANTY either expressed or implied. * You may study, use, and modify it for any non-commercial purpose, * including teaching and use in open-source projects. * You may distribute it non-commercially as long as you retain this notice. * For a commercial use license, or to purchase the book, * please visit http://www.davidflanagan.ru/javaexamples3. */
import java.awt.Color; import java.awt.FlowLayout; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionAdapter; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.TransferHandler; /**
* 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); }
}</source>
14. Drag and drop icons: 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.TransferHandler; 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 class IconDnD {
public static void main(String[] args) { JFrame f = new JFrame("Icon Drag & Drop"); ImageIcon icon1 = new ImageIcon("a.png"); ImageIcon icon2 = new ImageIcon("b.png"); ImageIcon icon3 = new ImageIcon("c.png"); JButton button = new JButton(icon2); 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")); f.setLayout(new FlowLayout()); f.add(label1); f.add(button); f.add(label2); f.pack(); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.setVisible(true); }
}</source>
14. Drag-and-Drop Support for Images
To transfer something other than a simple property, you need to create an implementation of the Transferable interface,
<source lang="java">
import java.awt.BorderLayout; import java.awt.Image; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.io.IOException; import javax.swing.AbstractButton; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JScrollPane; import javax.swing.TransferHandler; class ImageSelection extends TransferHandler implements Transferable {
private static final DataFlavor flavors[] = { DataFlavor.imageFlavor }; private Image image; public int getSourceActions(JComponent c) { return TransferHandler.COPY; } public boolean canImport(JComponent comp, DataFlavor flavor[]) { if (!(comp instanceof JLabel) && !(comp instanceof AbstractButton)) { return false; } for (int i = 0, n = flavor.length; i < n; i++) { for (int j = 0, m = flavors.length; j < m; j++) { if (flavor[i].equals(flavors[j])) { return true; } } } return false; } public Transferable createTransferable(JComponent comp) { // Clear image = null; if (comp instanceof JLabel) { JLabel label = (JLabel) comp; Icon icon = label.getIcon(); if (icon instanceof ImageIcon) { image = ((ImageIcon) icon).getImage(); return this; } } else if (comp instanceof AbstractButton) { AbstractButton button = (AbstractButton) comp; Icon icon = button.getIcon(); if (icon instanceof ImageIcon) { image = ((ImageIcon) icon).getImage(); return this; } } return null; } public boolean importData(JComponent comp, Transferable t) { if (comp instanceof JLabel) { JLabel label = (JLabel) comp; if (t.isDataFlavorSupported(flavors[0])) { try { image = (Image) t.getTransferData(flavors[0]); ImageIcon icon = new ImageIcon(image); label.setIcon(icon); return true; } catch (UnsupportedFlavorException ignored) { } catch (IOException ignored) { } } } else if (comp instanceof AbstractButton) { AbstractButton button = (AbstractButton) comp; if (t.isDataFlavorSupported(flavors[0])) { try { image = (Image) t.getTransferData(flavors[0]); ImageIcon icon = new ImageIcon(image); button.setIcon(icon); return true; } catch (UnsupportedFlavorException ignored) { } catch (IOException ignored) { } } } return false; } // Transferable public Object getTransferData(DataFlavor flavor) { if (isDataFlavorSupported(flavor)) { return image; } return null; } public DataFlavor[] getTransferDataFlavors() { return flavors; } public boolean isDataFlavorSupported(DataFlavor flavor) { return flavors[0].equals(flavor); }
} public class DragImage {
public static void main(String args[]) { JFrame frame = new JFrame("Drag Image"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); Icon icon = new ImageIcon("yourFile.gif"); JLabel label = new JLabel(icon); label.setTransferHandler(new ImageSelection()); MouseListener listener = new MouseAdapter() { public void mousePressed(MouseEvent me) { JComponent comp = (JComponent) me.getSource(); TransferHandler handler = comp.getTransferHandler(); handler.exportAsDrag(comp, me, TransferHandler.COPY); } }; label.addMouseListener(listener); frame.add(new JScrollPane(label), BorderLayout.CENTER); frame.setSize(300, 150); frame.setVisible(true); }
}</source>
14. Dragging and dropping text between a text area, a list, and a table
<source lang="java">
/*
* * Copyright (c) 1998 Sun Microsystems, Inc. All Rights Reserved. * * Sun grants you ("Licensee") a non-exclusive, royalty free, license to use, * modify and redistribute this software in source and binary code form, * provided that i) this copyright notice and license appear on all copies of * the software; and ii) Licensee does not utilize the software in a manner * which is disparaging to Sun. * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * This software is not designed or intended for use in on-line control of * aircraft, air traffic, aircraft navigation or aircraft communications; or in * the design, construction, operation or maintenance of any nuclear * facility. Licensee represents and warrants that it will not use or * redistribute the Software for such purposes. */
import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.GridLayout; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.StringSelection; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.io.IOException; import javax.swing.BorderFactory; import javax.swing.DefaultListModel; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.JTextArea; import javax.swing.ListSelectionModel; import javax.swing.TransferHandler; import javax.swing.table.DefaultTableModel; public class ExtendedDnDDemo extends JPanel {
public ExtendedDnDDemo() { super(new GridLayout(3,1)); add(createArea()); add(createList()); add(createTable()); } private JPanel createList() { DefaultListModel listModel = new DefaultListModel(); listModel.addElement("List 0"); listModel.addElement("List 1"); listModel.addElement("List 2"); listModel.addElement("List 3"); listModel.addElement("List 4"); listModel.addElement("List 5"); listModel.addElement("List 6"); listModel.addElement("List 7"); listModel.addElement("List 8"); JList list = new JList(listModel); list.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION); JScrollPane scrollPane = new JScrollPane(list); scrollPane.setPreferredSize(new Dimension(400,100)); list.setDragEnabled(true); list.setTransferHandler(new ListTransferHandler()); JPanel panel = new JPanel(new BorderLayout()); panel.add(scrollPane, BorderLayout.CENTER); panel.setBorder(BorderFactory.createTitledBorder("List")); return panel; } private JPanel createArea() { String text = "This is the text that I want to show."; JTextArea area = new JTextArea(); area.setText(text); area.setDragEnabled(true); JScrollPane scrollPane = new JScrollPane(area); scrollPane.setPreferredSize(new Dimension(400,100)); JPanel panel = new JPanel(new BorderLayout()); panel.add(scrollPane, BorderLayout.CENTER); panel.setBorder(BorderFactory.createTitledBorder("Text Area")); return panel; } private JPanel createTable() { DefaultTableModel model = new DefaultTableModel(); model.addColumn("Column 0"); model.addColumn("Column 1"); model.addColumn("Column 2"); model.addColumn("Column 3"); model.addRow(new String[]{"Table 00", "Table 01", "Table 02", "Table 03"}); model.addRow(new String[]{"Table 10", "Table 11", "Table 12", "Table 13"}); model.addRow(new String[]{"Table 20", "Table 21", "Table 22", "Table 23"}); model.addRow(new String[]{"Table 30", "Table 31", "Table 32", "Table 33"}); JTable table = new JTable(model); table.getTableHeader().setReorderingAllowed(false); table.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION); JScrollPane scrollPane = new JScrollPane(table); scrollPane.setPreferredSize(new Dimension(400,100)); table.setDragEnabled(true); table.setTransferHandler(new TableTransferHandler()); JPanel panel = new JPanel(new BorderLayout()); panel.add(scrollPane, BorderLayout.CENTER); panel.setBorder(BorderFactory.createTitledBorder("Table")); return panel; } /** * Create the GUI and show it. For thread safety, * this method should be invoked from the * event-dispatching thread. */ private static void createAndShowGUI() { //Create and set up the window. JFrame frame = new JFrame("ExtendedDnDDemo"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //Create and set up the content pane. JComponent newContentPane = new ExtendedDnDDemo(); newContentPane.setOpaque(true); //content panes must be opaque frame.setContentPane(newContentPane); //Display the window. frame.pack(); frame.setVisible(true); } public static void main(String[] args) { //Schedule a job for the event-dispatching thread: //creating and showing this application"s GUI. javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { createAndShowGUI(); } }); }
} abstract class StringTransferHandler extends TransferHandler {
protected abstract String exportString(JComponent c); protected abstract void importString(JComponent c, String str); protected abstract void cleanup(JComponent c, boolean remove); protected Transferable createTransferable(JComponent c) { return new StringSelection(exportString(c)); } public int getSourceActions(JComponent c) { return COPY_OR_MOVE; } public boolean importData(JComponent c, Transferable t) { if (canImport(c, t.getTransferDataFlavors())) { try { String str = (String)t.getTransferData(DataFlavor.stringFlavor); importString(c, str); return true; } catch (UnsupportedFlavorException ufe) { } catch (IOException ioe) { } } return false; } protected void exportDone(JComponent c, Transferable data, int action) { cleanup(c, action == MOVE); } public boolean canImport(JComponent c, DataFlavor[] flavors) { for (int i = 0; i < flavors.length; i++) { if (DataFlavor.stringFlavor.equals(flavors[i])) { return true; } } return false; }
} class ListTransferHandler extends StringTransferHandler {
private int[] indices = null; private int addIndex = -1; //Location where items were added private int addCount = 0; //Number of items added. //Bundle up the selected items in the list //as a single string, for export. protected String exportString(JComponent c) { JList list = (JList)c; indices = list.getSelectedIndices(); Object[] values = list.getSelectedValues(); StringBuffer buff = new StringBuffer(); for (int i = 0; i < values.length; i++) { Object val = values[i]; buff.append(val == null ? "" : val.toString()); if (i != values.length - 1) { buff.append("\n"); } } return buff.toString(); } //Take the incoming string and wherever there is a //newline, break it into a separate item in the list. protected void importString(JComponent c, String str) { JList target = (JList)c; DefaultListModel listModel = (DefaultListModel)target.getModel(); int index = target.getSelectedIndex(); //Prevent the user from dropping data back on itself. //For example, if the user is moving items #4,#5,#6 and #7 and //attempts to insert the items after item #5, this would //be problematic when removing the original items. //So this is not allowed. if (indices != null && index >= indices[0] - 1 && index <= indices[indices.length - 1]) { indices = null; return; } int max = listModel.getSize(); if (index < 0) { index = max; } else { index++; if (index > max) { index = max; } } addIndex = index; String[] values = str.split("\n"); addCount = values.length; for (int i = 0; i < values.length; i++) { listModel.add(index++, values[i]); } } //If the remove argument is true, the drop has been //successful and it"s time to remove the selected items //from the list. If the remove argument is false, it //was a Copy operation and the original list is left //intact. protected void cleanup(JComponent c, boolean remove) { if (remove && indices != null) { JList source = (JList)c; DefaultListModel model = (DefaultListModel)source.getModel(); //If we are moving items around in the same list, we //need to adjust the indices accordingly, since those //after the insertion point have moved. if (addCount > 0) { for (int i = 0; i < indices.length; i++) { if (indices[i] > addIndex) { indices[i] += addCount; } } } for (int i = indices.length - 1; i >= 0; i--) { model.remove(indices[i]); } } indices = null; addCount = 0; addIndex = -1; }
} class TableTransferHandler extends StringTransferHandler {
private int[] rows = null; private int addIndex = -1; //Location where items were added private int addCount = 0; //Number of items added. protected String exportString(JComponent c) { JTable table = (JTable)c; rows = table.getSelectedRows(); int colCount = table.getColumnCount(); StringBuffer buff = new StringBuffer(); for (int i = 0; i < rows.length; i++) { for (int j = 0; j < colCount; j++) { Object val = table.getValueAt(rows[i], j); buff.append(val == null ? "" : val.toString()); if (j != colCount - 1) { buff.append(","); } } if (i != rows.length - 1) { buff.append("\n"); } } return buff.toString(); } protected void importString(JComponent c, String str) { JTable target = (JTable)c; DefaultTableModel model = (DefaultTableModel)target.getModel(); int index = target.getSelectedRow(); //Prevent the user from dropping data back on itself. //For example, if the user is moving rows #4,#5,#6 and #7 and //attempts to insert the rows after row #5, this would //be problematic when removing the original rows. //So this is not allowed. if (rows != null && index >= rows[0] - 1 && index <= rows[rows.length - 1]) { rows = null; return; } int max = model.getRowCount(); if (index < 0) { index = max; } else { index++; if (index > max) { index = max; } } addIndex = index; String[] values = str.split("\n"); addCount = values.length; int colCount = target.getColumnCount(); for (int i = 0; i < values.length && i < colCount; i++) { model.insertRow(index++, values[i].split(",")); } } protected void cleanup(JComponent c, boolean remove) { JTable source = (JTable)c; if (remove && rows != null) { DefaultTableModel model = (DefaultTableModel)source.getModel(); //If we are moving items around in the same table, we //need to adjust the rows accordingly, since those //after the insertion point have moved. if (addCount > 0) { for (int i = 0; i < rows.length; i++) { if (rows[i] > addIndex) { rows[i] += addCount; } } } for (int i = rows.length - 1; i >= 0; i--) { model.removeRow(rows[i]); } } rows = null; addCount = 0; addIndex = -1; }
}</source>
14. Dragging Text from a JLabel
<source lang="java">
import java.awt.BorderLayout; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JTextField; import javax.swing.TransferHandler; public class DragLabel {
public static void main(String args[]) { JFrame frame = new JFrame("Drag Label"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JLabel label = new JLabel("Hello, World"); label.setTransferHandler(new TransferHandler("foreground")); MouseListener listener = new MouseAdapter() { public void mousePressed(MouseEvent me) { JComponent comp = (JComponent) me.getSource(); TransferHandler handler = comp.getTransferHandler(); handler.exportAsDrag(comp, me, TransferHandler.COPY); } }; label.addMouseListener(listener); frame.add(label, BorderLayout.SOUTH); JTextField text = new JTextField(); frame.add(text, BorderLayout.NORTH); frame.setSize(300, 150); frame.setVisible(true); }
}</source>
14. DropMode.INSERT
<source lang="java">
import java.awt.BorderLayout; import java.awt.Rectangle; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import javax.swing.DefaultListModel; import javax.swing.DropMode; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextField; import javax.swing.TransferHandler; public class DropModeINSERT {
public static void main(String[] args) { JPanel north = new JPanel(); north.add(new JLabel("Drag from here:")); JTextField field = new JTextField(10); field.setDragEnabled(true); north.add(field); final DefaultListModel listModel = new DefaultListModel(); listModel.addElement("first"); listModel.addElement("second"); final JList list = new JList(listModel); list.setDragEnabled(true); list.setTransferHandler(new TransferHandler() { public boolean canImport(TransferHandler.TransferSupport support) { if (!support.isDataFlavorSupported(DataFlavor.stringFlavor)) { return false; } JList.DropLocation dl = (JList.DropLocation) support.getDropLocation(); if (dl.getIndex() == -1) { return false; } else { return true; } } public boolean importData(TransferHandler.TransferSupport support) { if (!canImport(support)) { return false; } Transferable transferable = support.getTransferable(); String data; try { data = (String) transferable.getTransferData(DataFlavor.stringFlavor); } catch (Exception e) { return false; } JList.DropLocation dl = (JList.DropLocation) support.getDropLocation(); int index = dl.getIndex(); if (dl.isInsert()) { listModel.add(index, data); } else { listModel.set(index, data); } // Scroll to display the element that was dropped Rectangle r = list.getCellBounds(index, index); list.scrollRectToVisible(r); return true; } }); JScrollPane center = new JScrollPane(); center.setViewportView(list); list.setDropMode(DropMode.INSERT); JPanel cp = new JPanel(); cp.setLayout(new BorderLayout()); cp.add(north, BorderLayout.NORTH); cp.add(center, BorderLayout.CENTER); JFrame frame = new JFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setContentPane(cp); frame.pack(); frame.setVisible(true); }
}</source>
14. DropMode.ON
<source lang="java">
import java.awt.BorderLayout; import java.awt.Rectangle; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import javax.swing.DefaultListModel; import javax.swing.DropMode; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextField; import javax.swing.TransferHandler; public class DropModeON {
public static void main(String[] args) { JPanel north = new JPanel(); north.add(new JLabel("Drag from here:")); JTextField field = new JTextField(10); field.setDragEnabled(true); north.add(field); final DefaultListModel listModel = new DefaultListModel(); listModel.addElement("first"); listModel.addElement("second"); final JList list = new JList(listModel); list.setDragEnabled(true); list.setTransferHandler(new TransferHandler() { public boolean canImport(TransferHandler.TransferSupport support) { if (!support.isDataFlavorSupported(DataFlavor.stringFlavor)) { return false; } JList.DropLocation dl = (JList.DropLocation) support.getDropLocation(); if (dl.getIndex() == -1) { return false; } else { return true; } } public boolean importData(TransferHandler.TransferSupport support) { if (!canImport(support)) { return false; } Transferable transferable = support.getTransferable(); String data; try { data = (String) transferable.getTransferData(DataFlavor.stringFlavor); } catch (Exception e) { return false; } JList.DropLocation dl = (JList.DropLocation) support.getDropLocation(); int index = dl.getIndex(); if (dl.isInsert()) { listModel.add(index, data); } else { listModel.set(index, data); } // Scroll to display the element that was dropped Rectangle r = list.getCellBounds(index, index); list.scrollRectToVisible(r); return true; } }); JScrollPane center = new JScrollPane(); center.setViewportView(list); list.setDropMode(DropMode.ON); JPanel cp = new JPanel(); cp.setLayout(new BorderLayout()); cp.add(north, BorderLayout.NORTH); cp.add(center, BorderLayout.CENTER); JFrame frame = new JFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setContentPane(cp); frame.pack(); frame.setVisible(true); }
}</source>
14. DropMode.ON_OR_INSERT
<source lang="java">
import java.awt.BorderLayout; import java.awt.Rectangle; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import javax.swing.DefaultListModel; import javax.swing.DropMode; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextField; import javax.swing.TransferHandler; public class DropModeON_OR_INSERT {
public static void main(String[] args) { JPanel north = new JPanel(); north.add(new JLabel("Drag from here:")); JTextField field = new JTextField(10); field.setDragEnabled(true); north.add(field); final DefaultListModel listModel = new DefaultListModel(); listModel.addElement("first"); listModel.addElement("second"); final JList list = new JList(listModel); list.setDragEnabled(true); list.setTransferHandler(new TransferHandler() { public boolean canImport(TransferHandler.TransferSupport support) { if (!support.isDataFlavorSupported(DataFlavor.stringFlavor)) { return false; } JList.DropLocation dl = (JList.DropLocation) support.getDropLocation(); if (dl.getIndex() == -1) { return false; } else { return true; } } public boolean importData(TransferHandler.TransferSupport support) { if (!canImport(support)) { return false; } Transferable transferable = support.getTransferable(); String data; try { data = (String) transferable.getTransferData(DataFlavor.stringFlavor); } catch (Exception e) { return false; } JList.DropLocation dl = (JList.DropLocation) support.getDropLocation(); int index = dl.getIndex(); if (dl.isInsert()) { listModel.add(index, data); } else { listModel.set(index, data); } // Scroll to display the element that was dropped Rectangle r = list.getCellBounds(index, index); list.scrollRectToVisible(r); return true; } }); JScrollPane center = new JScrollPane(); center.setViewportView(list); list.setDropMode(DropMode.ON_OR_INSERT); JPanel cp = new JPanel(); cp.setLayout(new BorderLayout()); cp.add(north, BorderLayout.NORTH); cp.add(center, BorderLayout.CENTER); JFrame frame = new JFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setContentPane(cp); frame.pack(); frame.setVisible(true); }
}</source>
14. Illustrates cut, copy, paste and drag and drop using three instances of JList
<source lang="java">
/*
* Copyright (c) 1995 - 2008 Sun Microsystems, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * - Neither the name of Sun Microsystems nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
/**
* ListCutPaste.java requires the following files: * ListTransferHandler.java * TransferActionListener.java */
import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.GridLayout; import java.awt.KeyboardFocusManager; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.StringSelection; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.IOException; import javax.swing.Action; import javax.swing.ActionMap; import javax.swing.BorderFactory; import javax.swing.DefaultListModel; import javax.swing.DropMode; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JList; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.KeyStroke; import javax.swing.ListSelectionModel; import javax.swing.TransferHandler; import javax.swing.UIManager; /**
* The ListCutPaste example illustrates cut, copy, paste and drag and drop using * three instances of JList. The TransferActionListener class listens for one of * the CCP actions and, when one occurs, forwards the action to the component * which currently has the focus. */
public class ListCutPaste extends JPanel {
ListTransferHandler lh; public ListCutPaste() { super(new BorderLayout()); lh = new ListTransferHandler(); JPanel panel = new JPanel(new GridLayout(1, 3)); DefaultListModel list1Model = new DefaultListModel(); list1Model.addElement("alpha"); list1Model.addElement("beta"); list1Model.addElement("gamma"); list1Model.addElement("delta"); list1Model.addElement("epsilon"); list1Model.addElement("zeta"); JList list1 = new JList(list1Model); list1.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); JScrollPane sp1 = new JScrollPane(list1); sp1.setPreferredSize(new Dimension(400, 100)); list1.setDragEnabled(true); list1.setTransferHandler(lh); list1.setDropMode(DropMode.ON_OR_INSERT); setMappings(list1); JPanel pan1 = new JPanel(new BorderLayout()); pan1.add(sp1, BorderLayout.CENTER); pan1.setBorder(BorderFactory.createTitledBorder("Greek Alphabet")); panel.add(pan1); DefaultListModel list2Model = new DefaultListModel(); list2Model.addElement("uma"); list2Model.addElement("dois"); list2Model.addElement("tres"); list2Model.addElement("quatro"); list2Model.addElement("cinco"); list2Model.addElement("seis"); JList list2 = new JList(list2Model); list2.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); list2.setDragEnabled(true); JScrollPane sp2 = new JScrollPane(list2); sp2.setPreferredSize(new Dimension(400, 100)); list2.setTransferHandler(lh); list2.setDropMode(DropMode.INSERT); setMappings(list2); JPanel pan2 = new JPanel(new BorderLayout()); pan2.add(sp2, BorderLayout.CENTER); pan2.setBorder(BorderFactory.createTitledBorder("Portuguese Numbers")); panel.add(pan2); DefaultListModel list3Model = new DefaultListModel(); list3Model.addElement("adeen"); list3Model.addElement("dva"); list3Model.addElement("tri"); list3Model.addElement("chyetirye"); list3Model.addElement("pyat"); list3Model.addElement("shest"); JList list3 = new JList(list3Model); list3.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); list3.setDragEnabled(true); JScrollPane sp3 = new JScrollPane(list3); sp3.setPreferredSize(new Dimension(400, 100)); list3.setTransferHandler(lh); list3.setDropMode(DropMode.ON); setMappings(list3); JPanel pan3 = new JPanel(new BorderLayout()); pan3.add(sp3, BorderLayout.CENTER); pan3.setBorder(BorderFactory.createTitledBorder("Russian Numbers")); panel.add(pan3); setPreferredSize(new Dimension(500, 200)); add(panel, BorderLayout.CENTER); } /** * Create an Edit menu to support cut/copy/paste. */ public JMenuBar createMenuBar() { JMenuItem menuItem = null; JMenuBar menuBar = new JMenuBar(); JMenu mainMenu = new JMenu("Edit"); mainMenu.setMnemonic(KeyEvent.VK_E); TransferActionListener actionListener = new TransferActionListener(); menuItem = new JMenuItem("Cut"); menuItem.setActionCommand((String) TransferHandler.getCutAction().getValue( Action.NAME)); menuItem.addActionListener(actionListener); menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, ActionEvent.CTRL_MASK)); menuItem.setMnemonic(KeyEvent.VK_T); mainMenu.add(menuItem); menuItem = new JMenuItem("Copy"); menuItem.setActionCommand((String) TransferHandler.getCopyAction() .getValue(Action.NAME)); menuItem.addActionListener(actionListener); menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, ActionEvent.CTRL_MASK)); menuItem.setMnemonic(KeyEvent.VK_C); mainMenu.add(menuItem); menuItem = new JMenuItem("Paste"); menuItem.setActionCommand((String) TransferHandler.getPasteAction() .getValue(Action.NAME)); menuItem.addActionListener(actionListener); menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V, ActionEvent.CTRL_MASK)); menuItem.setMnemonic(KeyEvent.VK_P); mainMenu.add(menuItem); menuBar.add(mainMenu); return menuBar; } /** * Add the cut/copy/paste actions to the action map. */ private void setMappings(JList list) { ActionMap map = list.getActionMap(); map.put(TransferHandler.getCutAction().getValue(Action.NAME), TransferHandler.getCutAction()); map.put(TransferHandler.getCopyAction().getValue(Action.NAME), TransferHandler.getCopyAction()); map.put(TransferHandler.getPasteAction().getValue(Action.NAME), TransferHandler.getPasteAction()); } /** * Create the GUI and show it. For thread safety, this method should be * invoked from the event-dispatching thread. */ private static void createAndShowGUI() { // Create and set up the window. JFrame frame = new JFrame("ListCutPaste"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // Create and set up the menu bar and content pane. ListCutPaste demo = new ListCutPaste(); frame.setJMenuBar(demo.createMenuBar()); demo.setOpaque(true); // content panes must be opaque frame.setContentPane(demo); // Display the window. frame.pack(); frame.setVisible(true); } public static void main(String[] args) { // Schedule a job for the event-dispatching thread: // creating and showing this application"s GUI. javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { // Turn off metal"s use of bold fonts UIManager.put("swing.boldMetal", Boolean.FALSE); createAndShowGUI(); } }); }
}/*
* Copyright (c) 1995 - 2008 Sun Microsystems, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */
/*
* ListTransferHandler.java is used by the ListCutPaste example. */
class ListTransferHandler extends TransferHandler {
/** * Perform the actual data import. */ public boolean importData(TransferHandler.TransferSupport info) { String data = null; // If we can"t handle the import, bail now. if (!canImport(info)) { return false; } JList list = (JList) info.getComponent(); DefaultListModel model = (DefaultListModel) list.getModel(); // Fetch the data -- bail if this fails try { data = (String) info.getTransferable().getTransferData( DataFlavor.stringFlavor); } catch (UnsupportedFlavorException ufe) { System.out.println("importData: unsupported data flavor"); return false; } catch (IOException ioe) { System.out.println("importData: I/O exception"); return false; } if (info.isDrop()) { // This is a drop JList.DropLocation dl = (JList.DropLocation) info.getDropLocation(); int index = dl.getIndex(); if (dl.isInsert()) { model.add(index, data); return true; } else { model.set(index, data); return true; } } else { // This is a paste int index = list.getSelectedIndex(); // if there is a valid selection, // insert data after the selection if (index >= 0) { model.add(list.getSelectedIndex() + 1, data); // else append to the end of the list } else { model.addElement(data); } return true; } } /** * Bundle up the data for export. */ protected Transferable createTransferable(JComponent c) { JList list = (JList) c; int index = list.getSelectedIndex(); String value = (String) list.getSelectedValue(); return new StringSelection(value); } /** * The list handles both copy and move actions. */ public int getSourceActions(JComponent c) { return COPY_OR_MOVE; } /** * When the export is complete, remove the old list entry if the action was a * move. */ protected void exportDone(JComponent c, Transferable data, int action) { if (action != MOVE) { return; } JList list = (JList) c; DefaultListModel model = (DefaultListModel) list.getModel(); int index = list.getSelectedIndex(); model.remove(index); } /** * We only support importing strings. */ public boolean canImport(TransferHandler.TransferSupport support) { // we only import Strings if (!support.isDataFlavorSupported(DataFlavor.stringFlavor)) { return false; } return true; }
} /*
* Copyright (c) 1995 - 2008 Sun Microsystems, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */
/*
* TransferActionListener.java is used by the ListCutPaste example. */
/**
* A class that tracks the focused component. This is necessary to delegate the * menu cut/copy/paste commands to the right component. An instance of this * class is listening and when the user fires one of these commands, it calls * the appropriate action on the currently focused component. */
class TransferActionListener implements ActionListener, PropertyChangeListener {
private JComponent focusOwner = null; public TransferActionListener() { KeyboardFocusManager manager = KeyboardFocusManager .getCurrentKeyboardFocusManager(); manager.addPropertyChangeListener("permanentFocusOwner", this); } public void propertyChange(PropertyChangeEvent e) { Object o = e.getNewValue(); if (o instanceof JComponent) { focusOwner = (JComponent) o; } else { focusOwner = null; } } public void actionPerformed(ActionEvent e) { if (focusOwner == null) return; String action = (String) e.getActionCommand(); Action a = focusOwner.getActionMap().get(action); if (a != null) { a.actionPerformed(new ActionEvent(focusOwner, ActionEvent.ACTION_PERFORMED, null)); } }
}</source>
14. implements DragGestureListener, Transferable
<source lang="java">
import java.awt.Cursor; 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.JLabel; public class DragGesture extends JFrame implements DragGestureListener, Transferable {
public DragGesture() { setTitle("Drag Gesture"); JLabel left = new JLabel("text"); DragSource ds = new DragSource(); ds.createDefaultDragGestureRecognizer(left, DnDConstants.ACTION_COPY, this); add(left); pack(); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setVisible(true); } public void dragGestureRecognized(DragGestureEvent event) { Cursor cursor = null; if (event.getDragAction() == DnDConstants.ACTION_COPY) { cursor = DragSource.DefaultCopyDrop; } event.startDrag(cursor, this); } public Object getTransferData(DataFlavor flavor) { return null; } public DataFlavor[] getTransferDataFlavors() { return new DataFlavor[0]; } public boolean isDataFlavorSupported(DataFlavor flavor) { return false; } public static void main(String[] args) { new DragGesture(); }
}</source>
14. JTable drag and drop
<source lang="java">
/*
* Copyright (c) 1995 - 2008 Sun Microsystems, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * - Neither the name of Sun Microsystems nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.Rectangle; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.io.IOException; import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.DefaultListModel; import javax.swing.DropMode; import javax.swing.JCheckBoxMenuItem; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.ListSelectionModel; import javax.swing.SwingUtilities; import javax.swing.TransferHandler; import javax.swing.UIManager; import javax.swing.table.DefaultTableModel; public class FillViewportHeightDemo extends JFrame implements ActionListener {
private DefaultListModel model = new DefaultListModel(); private int count = 0; private JTable table; private JCheckBoxMenuItem fillBox; private DefaultTableModel tableModel; private static String getNextString(int count) { StringBuffer buf = new StringBuffer(); for (int i = 0; i < 5; i++) { buf.append(String.valueOf(count)); buf.append(","); } // remove last newline buf.deleteCharAt(buf.length() - 1); return buf.toString(); } private static DefaultTableModel getDefaultTableModel() { String[] cols = { "Foo", "Toto", "Kala", "Pippo", "Boing" }; return new DefaultTableModel(null, cols); } public FillViewportHeightDemo() { super("Empty Table DnD Demo"); tableModel = getDefaultTableModel(); table = new JTable(tableModel); table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); table.setDropMode(DropMode.INSERT_ROWS); table.setTransferHandler(new TransferHandler() { public boolean canImport(TransferSupport support) { // for the demo, we"ll only support drops (not clipboard paste) if (!support.isDrop()) { return false; } // we only import Strings if (!support.isDataFlavorSupported(DataFlavor.stringFlavor)) { return false; } return true; } public boolean importData(TransferSupport support) { // if we can"t handle the import, say so if (!canImport(support)) { return false; } // fetch the drop location JTable.DropLocation dl = (JTable.DropLocation) support .getDropLocation(); int row = dl.getRow(); // fetch the data and bail if this fails String data; try { data = (String) support.getTransferable().getTransferData( DataFlavor.stringFlavor); } catch (UnsupportedFlavorException e) { return false; } catch (IOException e) { return false; } String[] rowData = data.split(","); tableModel.insertRow(row, rowData); Rectangle rect = table.getCellRect(row, 0, false); if (rect != null) { table.scrollRectToVisible(rect); } // demo stuff - remove for blog model.removeAllElements(); model.insertElementAt(getNextString(count++), 0); // end demo stuff return true; } }); JList dragFrom = new JList(model); dragFrom.setFocusable(false); dragFrom.setPrototypeCellValue(getNextString(100)); model.insertElementAt(getNextString(count++), 0); dragFrom.setDragEnabled(true); dragFrom.setBorder(BorderFactory.createLoweredBevelBorder()); dragFrom.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent me) { if (SwingUtilities.isLeftMouseButton(me) && me.getClickCount() % 2 == 0) { String text = (String) model.getElementAt(0); String[] rowData = text.split(","); tableModel.insertRow(table.getRowCount(), rowData); model.removeAllElements(); model.insertElementAt(getNextString(count++), 0); } } }); JPanel p = new JPanel(); p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS)); JPanel wrap = new JPanel(); wrap.add(new JLabel("Drag from here:")); wrap.add(dragFrom); p.add(Box.createHorizontalStrut(4)); p.add(Box.createGlue()); p.add(wrap); p.add(Box.createGlue()); p.add(Box.createHorizontalStrut(4)); getContentPane().add(p, BorderLayout.NORTH); JScrollPane sp = new JScrollPane(table); getContentPane().add(sp, BorderLayout.CENTER); fillBox = new JCheckBoxMenuItem("Fill Viewport Height"); fillBox.addActionListener(this); JMenuBar mb = new JMenuBar(); JMenu options = new JMenu("Options"); mb.add(options); setJMenuBar(mb); JMenuItem clear = new JMenuItem("Reset"); clear.addActionListener(this); options.add(clear); options.add(fillBox); getContentPane().setPreferredSize(new Dimension(260, 180)); } public void actionPerformed(ActionEvent ae) { if (ae.getSource() == fillBox) { table.setFillsViewportHeight(fillBox.isSelected()); } else { tableModel.setRowCount(0); count = 0; model.removeAllElements(); model.insertElementAt(getNextString(count++), 0); } } private static void createAndShowGUI() { // Create and set up the window. FillViewportHeightDemo test = new FillViewportHeightDemo(); test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // Display the window. test.pack(); test.setVisible(true); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { // Turn off metal"s use of bold fonts UIManager.put("swing.boldMetal", Boolean.FALSE); createAndShowGUI(); } }); }
}</source>
14. Location sensitive drag and drop
<source lang="java">
/*
* Copyright (c) 1995 - 2008 Sun Microsystems, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * - Neither the name of Sun Microsystems nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.Font; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.UnsupportedFlavorException; import java.io.IOException; import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.DefaultListModel; import javax.swing.DropMode; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTree; import javax.swing.SwingUtilities; import javax.swing.TransferHandler; import javax.swing.UIManager; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreePath; import javax.swing.tree.TreeSelectionModel; public class LocationSensitiveDemo extends JFrame {
private DefaultListModel model = new DefaultListModel(); private int count = 0; private JTree tree; private JComboBox indicateCombo; private DefaultTreeModel treeModel; private TreePath namesPath; private static DefaultTreeModel getDefaultTreeModel() { DefaultMutableTreeNode root = new DefaultMutableTreeNode("things"); DefaultMutableTreeNode parent; DefaultMutableTreeNode nparent; parent = new DefaultMutableTreeNode("colors"); root.add(parent); parent.add(new DefaultMutableTreeNode("red")); parent.add(new DefaultMutableTreeNode("yellow")); parent.add(new DefaultMutableTreeNode("green")); parent.add(new DefaultMutableTreeNode("blue")); parent.add(new DefaultMutableTreeNode("purple")); parent = new DefaultMutableTreeNode("names"); root.add(parent); nparent = new DefaultMutableTreeNode("men"); nparent.add(new DefaultMutableTreeNode("jack")); nparent.add(new DefaultMutableTreeNode("kieran")); nparent.add(new DefaultMutableTreeNode("william")); nparent.add(new DefaultMutableTreeNode("jose")); parent.add(nparent); nparent = new DefaultMutableTreeNode("women"); nparent.add(new DefaultMutableTreeNode("jennifer")); nparent.add(new DefaultMutableTreeNode("holly")); nparent.add(new DefaultMutableTreeNode("danielle")); nparent.add(new DefaultMutableTreeNode("tara")); parent.add(nparent); parent = new DefaultMutableTreeNode("sports"); root.add(parent); parent.add(new DefaultMutableTreeNode("basketball")); parent.add(new DefaultMutableTreeNode("soccer")); parent.add(new DefaultMutableTreeNode("football")); nparent = new DefaultMutableTreeNode("hockey"); parent.add(nparent); nparent.add(new DefaultMutableTreeNode("ice hockey")); nparent.add(new DefaultMutableTreeNode("roller hockey")); nparent.add(new DefaultMutableTreeNode("floor hockey")); nparent.add(new DefaultMutableTreeNode("road hockey")); parent = new DefaultMutableTreeNode("food"); root.add(parent); parent.add(new DefaultMutableTreeNode("pizza")); parent.add(new DefaultMutableTreeNode("wings")); parent.add(new DefaultMutableTreeNode("pasta")); nparent = new DefaultMutableTreeNode("fruit"); parent.add(nparent); nparent.add(new DefaultMutableTreeNode("bananas")); nparent.add(new DefaultMutableTreeNode("apples")); nparent.add(new DefaultMutableTreeNode("grapes")); nparent.add(new DefaultMutableTreeNode("pears")); return new DefaultTreeModel(root); } public LocationSensitiveDemo() { super("Location Sensitive Drag and Drop Demo"); treeModel = getDefaultTreeModel(); tree = new JTree(treeModel); tree.setBorder(BorderFactory.createEmptyBorder(2, 4, 2, 4)); tree.getSelectionModel().setSelectionMode( TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION); tree.setDropMode(DropMode.ON); namesPath = tree.getPathForRow(2); tree.expandRow(2); tree.expandRow(1); tree.setRowHeight(0); tree.setTransferHandler(new TransferHandler() { public boolean canImport(TransferHandler.TransferSupport info) { // for the demo, we"ll only support drops (not clipboard paste) if (!info.isDrop()) { return false; } String item = (String) indicateCombo.getSelectedItem(); if (item.equals("Always")) { info.setShowDropLocation(true); } else if (item.equals("Never")) { info.setShowDropLocation(false); } // we only import Strings if (!info.isDataFlavorSupported(DataFlavor.stringFlavor)) { return false; } // fetch the drop location JTree.DropLocation dl = (JTree.DropLocation) info.getDropLocation(); TreePath path = dl.getPath(); // we don"t support invalid paths or descendants of the names folder if (path == null || namesPath.isDescendant(path)) { return false; } return true; } public boolean importData(TransferHandler.TransferSupport info) { // if we can"t handle the import, say so if (!canImport(info)) { return false; } // fetch the drop location JTree.DropLocation dl = (JTree.DropLocation) info.getDropLocation(); // fetch the path and child index from the drop location TreePath path = dl.getPath(); int childIndex = dl.getChildIndex(); // fetch the data and bail if this fails String data; try { data = (String) info.getTransferable().getTransferData( DataFlavor.stringFlavor); } catch (UnsupportedFlavorException e) { return false; } catch (IOException e) { return false; } // if child index is -1, the drop was on top of the path, so we"ll // treat it as inserting at the end of that path"s list of children if (childIndex == -1) { childIndex = tree.getModel().getChildCount( path.getLastPathComponent()); } // create a new node to represent the data and insert it into the model DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(data); DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode) path .getLastPathComponent(); treeModel.insertNodeInto(newNode, parentNode, childIndex); // make the new node visible and scroll so that it"s visible tree.makeVisible(path.pathByAddingChild(newNode)); tree.scrollRectToVisible(tree.getPathBounds(path .pathByAddingChild(newNode))); // demo stuff - remove for blog model.removeAllElements(); model.insertElementAt("String " + (++count), 0); // end demo stuff return true; } }); JList dragFrom = new JList(model); dragFrom.setFocusable(false); dragFrom.setPrototypeCellValue("String 0123456789"); model.insertElementAt("String " + count, 0); dragFrom.setDragEnabled(true); dragFrom.setBorder(BorderFactory.createLoweredBevelBorder()); JPanel p = new JPanel(); p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS)); JPanel wrap = new JPanel(); wrap.add(new JLabel("Drag from here:")); wrap.add(dragFrom); p.add(Box.createHorizontalStrut(4)); p.add(Box.createGlue()); p.add(wrap); p.add(Box.createGlue()); p.add(Box.createHorizontalStrut(4)); getContentPane().add(p, BorderLayout.NORTH); getContentPane().add(new JScrollPane(tree), BorderLayout.CENTER); indicateCombo = new JComboBox(new String[] { "Default", "Always", "Never" }); indicateCombo.setSelectedItem("INSERT"); p = new JPanel(); p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS)); wrap = new JPanel(); wrap.add(new JLabel("Show drop location:")); wrap.add(indicateCombo); p.add(Box.createHorizontalStrut(4)); p.add(Box.createGlue()); p.add(wrap); p.add(Box.createGlue()); p.add(Box.createHorizontalStrut(4)); getContentPane().add(p, BorderLayout.SOUTH); getContentPane().setPreferredSize(new Dimension(400, 450)); } private static void increaseFont(String type) { Font font = UIManager.getFont(type); font = font.deriveFont(font.getSize() + 4f); UIManager.put(type, font); } private static void createAndShowGUI() { // Create and set up the window. LocationSensitiveDemo test = new LocationSensitiveDemo(); test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // Display the window. test.pack(); test.setVisible(true); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { try { UIManager .setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); increaseFont("Tree.font"); increaseFont("Label.font"); increaseFont("ComboBox.font"); increaseFont("List.font"); } catch (Exception e) { } // Turn off metal"s use of bold fonts UIManager.put("swing.boldMetal", Boolean.FALSE); createAndShowGUI(); } }); }
}</source>
14. Making a Component Draggable
<source lang="java">
import java.awt.datatransfer.StringSelection; 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 java.awt.dnd.DragSourceDragEvent; import java.awt.dnd.DragSourceDropEvent; import java.awt.dnd.DragSourceEvent; import java.awt.dnd.DragSourceListener; import javax.swing.JComponent; import javax.swing.JFrame; public class Main {
public static void main(String[] argv) throws Exception { JComponent com = new DraggableComponent(); JFrame f = new JFrame(); f.add(com); f.setSize(300, 300); f.setVisible(true); }
} class DraggableComponent extends JComponent implements DragGestureListener, DragSourceListener {
DragSource dragSource; public DraggableComponent() { dragSource = new DragSource(); dragSource.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_COPY_OR_MOVE, this); } public void dragGestureRecognized(DragGestureEvent evt) { Transferable t = new StringSelection("aString"); dragSource.startDrag(evt, DragSource.DefaultCopyDrop, t, this); } public void dragEnter(DragSourceDragEvent evt) { System.out.println("enters"); } public void dragOver(DragSourceDragEvent evt) { System.out.println("over"); } public void dragExit(DragSourceEvent evt) { System.out.println("leaves"); } public void dropActionChanged(DragSourceDragEvent evt) { System.out.println("changes the drag action between copy or move"); } public void dragDropEnd(DragSourceDropEvent evt) { System.out.println("finishes or cancels the drag operation"); }
}</source>
14. ScribblePane allows individual PolyLine lines to be selected, cut, copied, pasted, dragged, and dropped
<source lang="java">
/*
* Copyright (c) 2004 David Flanagan. All rights reserved. * This code is from the book Java Examples in a Nutshell, 3nd Edition. * It is provided AS-IS, WITHOUT ANY WARRANTY either expressed or implied. * You may study, use, and modify it for any non-commercial purpose, * including teaching and use in open-source projects. * You may distribute it non-commercially as long as you retain this notice. * For a commercial use license, or to purchase the book, * please visit http://www.davidflanagan.ru/javaexamples3. */
import java.awt.AWTEvent; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.Point; import java.awt.Rectangle; import java.awt.Shape; import java.awt.Stroke; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.ClipboardOwner; 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.DragSourceDragEvent; import java.awt.dnd.DragSourceDropEvent; import java.awt.dnd.DragSourceEvent; import java.awt.dnd.DragSourceListener; import java.awt.dnd.DropTarget; import java.awt.dnd.DropTargetDragEvent; import java.awt.dnd.DropTargetDropEvent; import java.awt.dnd.DropTargetEvent; import java.awt.dnd.DropTargetListener; import java.awt.event.MouseEvent; import java.awt.geom.AffineTransform; import java.awt.geom.PathIterator; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.io.Externalizable; import java.util.ArrayList; import java.util.List; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.border.BevelBorder; import javax.swing.border.Border; import javax.swing.border.LineBorder; /**
* This rewrite of ScribblePane allows individual PolyLine lines to be selected, * cut, copied, pasted, dragged, and dropped. */
public class TransferableScribblePane extends JComponent {
List lines; // The PolyLines that comprise this scribble PolyLine currentLine; // The line currently being drawn PolyLine selectedLine; // The line that is current selected boolean canDragImage; // Can we drag an image of the line? // Lines are 3 pixels wide, and the selected line is drawn dashed static Stroke stroke = new BasicStroke(3.0f); static Stroke selectedStroke = new BasicStroke(3, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND, 0f, new float[] { 3f, 3f, }, 0f); // Different borders indicate receptivity to drops static Border normalBorder = new LineBorder(Color.black, 3); static Border canDropBorder = new BevelBorder(BevelBorder.LOWERED); public static void main(String args[]) { JFrame f = new JFrame("ColorDrag"); f.getContentPane().setLayout(new FlowLayout()); f.getContentPane().add(new TransferableScribblePane()); f.getContentPane().add(new TransferableScribblePane()); f.pack(); f.setVisible(true); } // The constructor method public TransferableScribblePane() { setPreferredSize(new Dimension(450, 200)); // We need a default size setBorder(normalBorder); // and a border. lines = new ArrayList(); // Start with an empty list of lines // Register interest in mouse button and mouse motion events. enableEvents(AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK); // Enable drag-and-drop by specifying a listener that will be // notified when a drag begins. dragGestureListener is defined later. DragSource dragSource = DragSource.getDefaultDragSource(); dragSource.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_COPY_OR_MOVE, dragGestureListener); // Enable drops on this component by registering a listener to // be notified when something is dragged or dropped over us. this.setDropTarget(new DropTarget(this, dropTargetListener)); // Check whether the system allows us to drag an image of the line canDragImage = dragSource.isDragImageSupported(); } /** We override this method to draw ourselves. */ public void paintComponent(Graphics g) { // Let the superclass do its painting first super.paintComponent(g); // Make a copy of the Graphics context so we can modify it Graphics2D g2 = (Graphics2D) (g.create()); // Our superclass doesn"t paint the background, so do this ourselves. g2.setColor(getBackground()); g2.fillRect(0, 0, getWidth(), getHeight()); // Set the line width and color to use for the foreground g2.setStroke(stroke); g2.setColor(this.getForeground()); // Now loop through the PolyLine shapes and draw them all int numlines = lines.size(); for (int i = 0; i < numlines; i++) { PolyLine line = (PolyLine) lines.get(i); if (line == selectedLine) { // If it is the selected line g2.setStroke(selectedStroke); // Set dash pattern g2.draw(line); // Draw the line g2.setStroke(stroke); // Revert to solid lines } else g2.draw(line); // Otherwise just draw the line } } /** * This method is called on mouse button events. It begins a new line or tries * to select an existing line. */ public void processMouseEvent(MouseEvent e) { if (e.getButton() == MouseEvent.BUTTON1) { // Left mouse button if (e.getID() == MouseEvent.MOUSE_PRESSED) { // Pressed down if (e.isShiftDown()) { // with Shift key // If the shift key is down, try to select a line int x = e.getX(); int y = e.getY(); // Loop through the lines checking to see if we hit one PolyLine selection = null; int numlines = lines.size(); for (int i = 0; i < numlines; i++) { PolyLine line = (PolyLine) lines.get(i); if (line.intersects(x - 2, y - 2, 4, 4)) { selection = line; e.consume(); break; } } // If we found an intersecting line, save it and repaint if (selection != selectedLine) { // If selection changed selectedLine = selection; // remember which is selected repaint(); // will make selection dashed } } else if (!e.isControlDown()) { // no shift key or ctrl key // Start a new line on mouse down without shift or ctrl currentLine = new PolyLine(e.getX(), e.getY()); lines.add(currentLine); e.consume(); } } else if (e.getID() == MouseEvent.MOUSE_RELEASED) {// Left Button Up // End the line on mouse up if (currentLine != null) { currentLine = null; e.consume(); } } } // The superclass method dispatches to registered event listeners super.processMouseEvent(e); } /** * This method is called for mouse motion events. We don"t have to detect * gestures that initiate a drag in this method. That is the job of the * DragGestureRecognizer we created in the constructor: it will notify the * DragGestureListener defined below. */ public void processMouseMotionEvent(MouseEvent e) { if (e.getID() == MouseEvent.MOUSE_DRAGGED && // If we"re dragging currentLine != null) { // and a line exists currentLine.addSegment(e.getX(), e.getY()); // Add a line segment e.consume(); // Eat the event repaint(); // Redisplay all lines } super.processMouseMotionEvent(e); // Invoke any listeners } /** Copy the selected line to the clipboard, then delete it */ public void cut() { if (selectedLine == null) return; // Only works if a line is selected copy(); // Do a Copy operation... lines.remove(selectedLine); // and then erase the selected line selectedLine = null; repaint(); // Repaint because a line was removed } /** Copy the selected line to the clipboard */ public void copy() { if (selectedLine == null) return; // Only works if a line is selected // Get the system Clipboard object. Clipboard c = this.getToolkit().getSystemClipboard(); // Wrap the selected line in a TransferablePolyLine object // and pass it to the clipboard, with an object to receive notification // when some other application takes ownership of the clipboard c.setContents(new TransferablePolyLine((PolyLine) selectedLine.clone()), new ClipboardOwner() { public void lostOwnership(Clipboard c, Transferable t) { // This method is called when something else // is copied to the clipboard. We could use it // to deselect the selected line, if we wanted. } }); } /** Get a PolyLine from the clipboard, if one exists, and display it */ public void paste() { // Get the system Clipboard and ask for its Transferable contents Clipboard c = this.getToolkit().getSystemClipboard(); Transferable t = c.getContents(this); // See if we can extract a PolyLine from the Transferable object PolyLine line; try { line = (PolyLine) t.getTransferData(TransferablePolyLine.FLAVOR); } catch (Exception e) { // UnsupportedFlavorException or IOException // If we get here, the clipboard doesn"t hold a PolyLine we can use getToolkit().beep(); // So beep to indicate the error return; } lines.add(line); // We got a line from the clipboard, so add it to list repaint(); // And repaint to make the line appear } /** Erase all lines and repaint. */ public void clear() { lines.clear(); repaint(); } /** * This DragGestureListener is notified when the user initiates a drag. We * passed it to the DragGestureRecognizer we created in the constructor. */ public DragGestureListener dragGestureListener = new DragGestureListener() { public void dragGestureRecognized(DragGestureEvent e) { // Don"t start a drag if there isn"t a selected line if (selectedLine == null) return; // Find out where the drag began MouseEvent trigger = (MouseEvent) e.getTriggerEvent(); int x = trigger.getX(); int y = trigger.getY(); // Don"t do anything if the drag was not near the selected line if (!selectedLine.intersects(x - 4, y - 4, 8, 8)) return; // Make a copy of the selected line, adjust the copy so that // the point under the mouse is (0,0), and wrap the copy in a // Tranferable wrapper. PolyLine copy = (PolyLine) selectedLine.clone(); copy.translate(-x, -y); Transferable t = new TransferablePolyLine(copy); // If the system allows custom images to be dragged, make // an image of the line on a transparent background Image dragImage = null; Point hotspot = null; if (canDragImage) { Rectangle box = copy.getBounds(); dragImage = createImage(box.width, box.height); Graphics2D g = (Graphics2D) dragImage.getGraphics(); g.setColor(new Color(0, 0, 0, 0)); // transparent bg g.fillRect(0, 0, box.width, box.height); g.setColor(getForeground()); g.setStroke(selectedStroke); g.translate(-box.x, -box.y); g.draw(copy); hotspot = new Point(-box.x, -box.y); } // Now begin dragging the line, specifying the listener // object to receive notifications about the progress of // the operation. Note: the startDrag() method is defined by // the event object, which is unusual. e.startDrag(null, // Use default drag-and-drop cursors dragImage, // Use the image, if supported hotspot, // Ditto for the image hotspot t, // Drag this object dragSourceListener); // Send notifications here } }; /** * If this component is the source of a drag, then this DragSourceListener * will receive notifications about the progress of the drag. The only one we * use here is dragDropEnd() which is called after a drop occurs. We could use * the other methods to change cursors or perform other "drag over effects" */ public DragSourceListener dragSourceListener = new DragSourceListener() { // Invoked when dragging stops public void dragDropEnd(DragSourceDropEvent e) { if (!e.getDropSuccess()) return; // Ignore failed drops // If the drop was a move, then delete the selected line if (e.getDropAction() == DnDConstants.ACTION_MOVE) { lines.remove(selectedLine); selectedLine = null; repaint(); } } // The following methods are unused here. We could implement them // to change custom cursors or perform other "drag over effects". public void dragEnter(DragSourceDragEvent e) { } public void dragExit(DragSourceEvent e) { } public void dragOver(DragSourceDragEvent e) { } public void dropActionChanged(DragSourceDragEvent e) { } }; /** * This DropTargetListener is notified when something is dragged over this * component. */ public DropTargetListener dropTargetListener = new DropTargetListener() { // This method is called when something is dragged over us. // If we understand what is being dragged, then tell the system // we can accept it, and change our border to provide extra // "drag under" visual feedback to the user to indicate our // receptivity to a drop. public void dragEnter(DropTargetDragEvent e) { if (e.isDataFlavorSupported(TransferablePolyLine.FLAVOR)) { e.acceptDrag(e.getDropAction()); setBorder(canDropBorder); } } // Revert to our normal border if the drag moves off us. public void dragExit(DropTargetEvent e) { setBorder(normalBorder); } // This method is called when something is dropped on us. public void drop(DropTargetDropEvent e) { // If a PolyLine is dropped, accept either a COPY or a MOVE if (e.isDataFlavorSupported(TransferablePolyLine.FLAVOR)) e.acceptDrop(e.getDropAction()); else { // Otherwise, reject the drop and return e.rejectDrop(); return; } // Get the dropped object and extract a PolyLine from it Transferable t = e.getTransferable(); PolyLine line; try { line = (PolyLine) t.getTransferData(TransferablePolyLine.FLAVOR); } catch (Exception ex) { // UnsupportedFlavor or IOException getToolkit().beep(); // Something went wrong, so beep e.dropComplete(false); // Tell the system we failed return; } // Figure out where the drop occurred, and translate so the // point that was formerly (0,0) is now at that point. Point p = e.getLocation(); line.translate((float) p.getX(), (float) p.getY()); // Add the line to our list, and repaint lines.add(line); repaint(); // Tell the system that we successfully completed the transfer. // This means it is safe for the initiating component to delete // its copy of the line e.dropComplete(true); } // We could provide additional drag under effects with this method. public void dragOver(DropTargetDragEvent e) { } // If we used custom cursors, we would update them here. public void dropActionChanged(DropTargetDragEvent e) { } };
} /**
* This Shape implementation represents a series of connected line segments. It * is like a Polygon, but is not closed. This class is used by the ScribblePane * class of the GUI chapter. It implements the Cloneable and Externalizable * interfaces so it can be used in the Drag-and-Drop examples in the Data * Transfer chapter. */
class PolyLine implements Shape, Cloneable, Externalizable {
float x0, y0; // The starting point of the polyline. float[] coords; // The x and y coordinates of the end point of each line // segment packed into a single array for simplicity: // [x1,y1,x2,y2,...] Note that these are relative to x0,y0 int numsegs; // How many line segments in this PolyLine // Coordinates of our bounding box, relative to (x0, y0); float xmin = 0f, xmax = 0f, ymin = 0f, ymax = 0f; // No arg constructor assumes an origin of (0,0) // A no-arg constructor is required for the Externalizable interface public PolyLine() { this(0f, 0f); } // The constructor. public PolyLine(float x0, float y0) { setOrigin(x0, y0); // Record the starting point. numsegs = 0; // Note that we have no line segments, so far } /** Set the origin of the PolyLine. Useful when moving it */ public void setOrigin(float x0, float y0) { this.x0 = x0; this.y0 = y0; } /** Add dx and dy to the origin */ public void translate(float dx, float dy) { this.x0 += dx; this.y0 += dy; } /** * Add a line segment to the PolyLine. Note that x and y are absolute * coordinates, even though the implementation stores them relative to x0, y0; */ public void addSegment(float x, float y) { // Allocate or reallocate the coords[] array when necessary if (coords == null) coords = new float[32]; if (numsegs * 2 >= coords.length) { float[] newcoords = new float[coords.length * 2]; System.arraycopy(coords, 0, newcoords, 0, coords.length); coords = newcoords; } // Convert from absolute to relative coordinates x = x - x0; y = y - y0; // Store the data coords[numsegs * 2] = x; coords[numsegs * 2 + 1] = y; numsegs++; // Enlarge the bounding box, if necessary if (x > xmax) xmax = x; else if (x < xmin) xmin = x; if (y > ymax) ymax = y; else if (y < ymin) ymin = y; } /*------------------ The Shape Interface --------------------- */ // Return floating-point bounding box public Rectangle2D getBounds2D() { return new Rectangle2D.Float(x0 + xmin, y0 + ymin, xmax - xmin, ymax - ymin); } // Return integer bounding box, rounded to outermost pixels. public Rectangle getBounds() { return new Rectangle((int) (x0 + xmin - 0.5f), // x0 (int) (y0 + ymin - 0.5f), // y0 (int) (xmax - xmin + 0.5f), // width (int) (ymax - ymin + 0.5f)); // height } // PolyLine shapes are open curves, with no interior. // The Shape interface says that open curves should be implicitly closed // for the purposes of insideness testing. For our purposes, however, // we define PolyLine shapes to have no interior, and the contains() // methods always return false. public boolean contains(Point2D p) { return false; } public boolean contains(Rectangle2D r) { return false; } public boolean contains(double x, double y) { return false; } public boolean contains(double x, double y, double w, double h) { return false; } // The intersects methods simply test whether any of the line segments // within a polyline intersects the given rectangle. Strictly speaking, // the Shape interface requires us to also check whether the rectangle // is entirely contained within the shape as well. But the contains() // methods for this class alwasy return false. // We might improve the efficiency of this method by first checking for // intersection with the overall bounding box to rule out cases that // aren"t even close. public boolean intersects(Rectangle2D r) { if (numsegs < 1) return false; float lastx = x0, lasty = y0; for (int i = 0; i < numsegs; i++) { // loop through the segments float x = coords[i * 2] + x0; float y = coords[i * 2 + 1] + y0; // See if this line segment intersects the rectangle if (r.intersectsLine(x, y, lastx, lasty)) return true; // Otherwise move on to the next segment lastx = x; lasty = y; } return false; // No line segment intersected the rectangle } // This variant method is just defined in terms of the last. public boolean intersects(double x, double y, double w, double h) { return intersects(new Rectangle2D.Double(x, y, w, h)); } // This is the key to the Shape interface; it tells Java2D how to draw // the shape as a series of lines and curves. We use only lines public PathIterator getPathIterator(final AffineTransform transform) { return new PathIterator() { int curseg = -1; // current segment // Copy the current segment for thread-safety, so we don"t // mess up of a segment is added while we"re iterating int numsegs = PolyLine.this.numsegs; public boolean isDone() { return curseg >= numsegs; } public void next() { curseg++; } // Get coordinates and type of current segment as floats public int currentSegment(float[] data) { int segtype; if (curseg == -1) { // First time we"re called data[0] = x0; // Data is the origin point data[1] = y0; segtype = SEG_MOVETO; // Returned as a moveto segment } else { // Otherwise, the data is a segment endpoint data[0] = x0 + coords[curseg * 2]; data[1] = y0 + coords[curseg * 2 + 1]; segtype = SEG_LINETO; // Returned as a lineto segment } // If a tranform was specified, transform point in place if (transform != null) transform.transform(data, 0, data, 0, 1); return segtype; } // Same as last method, but use doubles public int currentSegment(double[] data) { int segtype; if (curseg == -1) { data[0] = x0; data[1] = y0; segtype = SEG_MOVETO; } else { data[0] = x0 + coords[curseg * 2]; data[1] = y0 + coords[curseg * 2 + 1]; segtype = SEG_LINETO; } if (transform != null) transform.transform(data, 0, data, 0, 1); return segtype; } // This only matters for closed shapes public int getWindingRule() { return WIND_NON_ZERO; } }; } // PolyLines never contain curves, so we can ignore the flatness limit // and implement this method in terms of the one above. public PathIterator getPathIterator(AffineTransform at, double flatness) { return getPathIterator(at); } /*------------------ Externalizable --------------------- */ /** * The following two methods implement the Externalizable interface. We use * Externalizable instead of Seralizable so we have full control over the data * format, and only write out the defined coordinates */ public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException { out.writeFloat(x0); out.writeFloat(y0); out.writeInt(numsegs); for (int i = 0; i < numsegs * 2; i++) out.writeFloat(coords[i]); } public void readExternal(java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException { this.x0 = in.readFloat(); this.y0 = in.readFloat(); this.numsegs = in.readInt(); this.coords = new float[numsegs * 2]; for (int i = 0; i < numsegs * 2; i++) coords[i] = in.readFloat(); } /*------------------ Cloneable --------------------- */ /** * Override the Object.clone() method so that the array gets cloned, too. */ public Object clone() { try { PolyLine copy = (PolyLine) super.clone(); if (coords != null) copy.coords = (float[]) this.coords.clone(); return copy; } catch (CloneNotSupportedException e) { throw new AssertionError(); // This should never happen } }
} /*
* Copyright (c) 2004 David Flanagan. All rights reserved. This code is from the * book Java Examples in a Nutshell, 3nd Edition. It is provided AS-IS, WITHOUT * ANY WARRANTY either expressed or implied. You may study, use, and modify it * for any non-commercial purpose, including teaching and use in open-source * projects. You may distribute it non-commercially as long as you retain this * notice. For a commercial use license, or to purchase the book, please visit * http://www.davidflanagan.ru/javaexamples3. */
/**
* This class implements the Transferable interface for PolyLine objects. It * also defines a DataFlavor used to describe this data type. */
class TransferablePolyLine implements Transferable {
public static DataFlavor FLAVOR = new DataFlavor(PolyLine.class, "PolyLine"); static DataFlavor[] FLAVORS = new DataFlavor[] { FLAVOR }; PolyLine line; // This is the PolyLine we wrap. public TransferablePolyLine(PolyLine line) { this.line = line; } /** Return the supported flavor */ public DataFlavor[] getTransferDataFlavors() { return FLAVORS; } /** Check for the one flavor we support */ public boolean isDataFlavorSupported(DataFlavor f) { return f.equals(FLAVOR); } /** Return the wrapped PolyLine, if the flavor is right */ public Object getTransferData(DataFlavor f) throws UnsupportedFlavorException { if (!f.equals(FLAVOR)) throw new UnsupportedFlavorException(f); return line; }
}</source>
14. Set tree drag mode to DropMode.INSERT
<source lang="java">
import java.awt.BorderLayout; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.IOException; import javax.swing.DropMode; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextField; import javax.swing.JTree; import javax.swing.TransferHandler; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreePath; public class DndTree {
public static void main(String args[]) { JFrame f = new JFrame(); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JPanel top = new JPanel(new BorderLayout()); JLabel dragLabel = new JLabel("Drag me:"); JTextField text = new JTextField(); text.setDragEnabled(true); top.add(dragLabel, BorderLayout.WEST); top.add(text, BorderLayout.CENTER); f.add(top, BorderLayout.NORTH); final JTree tree = new JTree(); final DefaultTreeModel model = (DefaultTreeModel) tree.getModel(); tree.setTransferHandler(new TransferHandler() { public boolean canImport(TransferHandler.TransferSupport support) { if (!support.isDataFlavorSupported(DataFlavor.stringFlavor) || !support.isDrop()) { return false; } JTree.DropLocation dropLocation = (JTree.DropLocation) support.getDropLocation(); return dropLocation.getPath() != null; } public boolean importData(TransferHandler.TransferSupport support) { if (!canImport(support)) { return false; } JTree.DropLocation dropLocation = (JTree.DropLocation) support.getDropLocation(); TreePath path = dropLocation.getPath(); Transferable transferable = support.getTransferable(); String transferData; try { transferData = (String) transferable.getTransferData(DataFlavor.stringFlavor); } catch (IOException e) { return false; } catch (UnsupportedFlavorException e) { return false; } int childIndex = dropLocation.getChildIndex(); if (childIndex == -1) { childIndex = model.getChildCount(path.getLastPathComponent()); } DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(transferData); DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode) path.getLastPathComponent(); model.insertNodeInto(newNode, parentNode, childIndex); TreePath newPath = path.pathByAddingChild(newNode); tree.makeVisible(newPath); tree.scrollRectToVisible(tree.getPathBounds(newPath)); return true; } }); JScrollPane pane = new JScrollPane(tree); f.add(pane, BorderLayout.CENTER); tree.setDropMode(DropMode.INSERT); f.setSize(300, 400); f.setVisible(true); }
}</source>
14. Set tree drag mode to DropMode.ON
<source lang="java">
import java.awt.BorderLayout; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.IOException; import javax.swing.DropMode; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextField; import javax.swing.JTree; import javax.swing.TransferHandler; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreePath; public class DndTree {
public static void main(String args[]) { JFrame f = new JFrame(); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JPanel top = new JPanel(new BorderLayout()); JLabel dragLabel = new JLabel("Drag me:"); JTextField text = new JTextField(); text.setDragEnabled(true); top.add(dragLabel, BorderLayout.WEST); top.add(text, BorderLayout.CENTER); f.add(top, BorderLayout.NORTH); final JTree tree = new JTree(); final DefaultTreeModel model = (DefaultTreeModel) tree.getModel(); tree.setTransferHandler(new TransferHandler() { public boolean canImport(TransferHandler.TransferSupport support) { if (!support.isDataFlavorSupported(DataFlavor.stringFlavor) || !support.isDrop()) { return false; } JTree.DropLocation dropLocation = (JTree.DropLocation) support.getDropLocation(); return dropLocation.getPath() != null; } public boolean importData(TransferHandler.TransferSupport support) { if (!canImport(support)) { return false; } JTree.DropLocation dropLocation = (JTree.DropLocation) support.getDropLocation(); TreePath path = dropLocation.getPath(); Transferable transferable = support.getTransferable(); String transferData; try { transferData = (String) transferable.getTransferData(DataFlavor.stringFlavor); } catch (IOException e) { return false; } catch (UnsupportedFlavorException e) { return false; } int childIndex = dropLocation.getChildIndex(); if (childIndex == -1) { childIndex = model.getChildCount(path.getLastPathComponent()); } DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(transferData); DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode) path.getLastPathComponent(); model.insertNodeInto(newNode, parentNode, childIndex); TreePath newPath = path.pathByAddingChild(newNode); tree.makeVisible(newPath); tree.scrollRectToVisible(tree.getPathBounds(newPath)); return true; } }); JScrollPane pane = new JScrollPane(tree); f.add(pane, BorderLayout.CENTER); tree.setDropMode(DropMode.ON); f.setSize(300, 400); f.setVisible(true); }
}</source>
14. Set tree drag mode to DropMode.ON_OR_INSERT
<source lang="java">
import java.awt.BorderLayout; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.IOException; import javax.swing.DropMode; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextField; import javax.swing.JTree; import javax.swing.TransferHandler; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreePath; public class DndTree {
public static void main(String args[]) { JFrame f = new JFrame(); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JPanel top = new JPanel(new BorderLayout()); JLabel dragLabel = new JLabel("Drag me:"); JTextField text = new JTextField(); text.setDragEnabled(true); top.add(dragLabel, BorderLayout.WEST); top.add(text, BorderLayout.CENTER); f.add(top, BorderLayout.NORTH); final JTree tree = new JTree(); final DefaultTreeModel model = (DefaultTreeModel) tree.getModel(); tree.setTransferHandler(new TransferHandler() { public boolean canImport(TransferHandler.TransferSupport support) { if (!support.isDataFlavorSupported(DataFlavor.stringFlavor) || !support.isDrop()) { return false; } JTree.DropLocation dropLocation = (JTree.DropLocation) support.getDropLocation(); return dropLocation.getPath() != null; } public boolean importData(TransferHandler.TransferSupport support) { if (!canImport(support)) { return false; } JTree.DropLocation dropLocation = (JTree.DropLocation) support.getDropLocation(); TreePath path = dropLocation.getPath(); Transferable transferable = support.getTransferable(); String transferData; try { transferData = (String) transferable.getTransferData(DataFlavor.stringFlavor); } catch (IOException e) { return false; } catch (UnsupportedFlavorException e) { return false; } int childIndex = dropLocation.getChildIndex(); if (childIndex == -1) { childIndex = model.getChildCount(path.getLastPathComponent()); } DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(transferData); DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode) path.getLastPathComponent(); model.insertNodeInto(newNode, parentNode, childIndex); TreePath newPath = path.pathByAddingChild(newNode); tree.makeVisible(newPath); tree.scrollRectToVisible(tree.getPathBounds(newPath)); return true; } }); JScrollPane pane = new JScrollPane(tree); f.add(pane, BorderLayout.CENTER); tree.setDropMode(DropMode.ON_OR_INSERT); f.setSize(300, 400); f.setVisible(true); }
}</source>
14. Set tree DropMode to DropMode.USE_SELECTION
<source lang="java">
import java.awt.BorderLayout; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.IOException; import javax.swing.DropMode; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextField; import javax.swing.JTree; import javax.swing.TransferHandler; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreePath; public class DndTree {
public static void main(String args[]) { JFrame f = new JFrame(); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JPanel top = new JPanel(new BorderLayout()); JLabel dragLabel = new JLabel("Drag me:"); JTextField text = new JTextField(); text.setDragEnabled(true); top.add(dragLabel, BorderLayout.WEST); top.add(text, BorderLayout.CENTER); f.add(top, BorderLayout.NORTH); final JTree tree = new JTree(); final DefaultTreeModel model = (DefaultTreeModel) tree.getModel(); tree.setTransferHandler(new TransferHandler() { public boolean canImport(TransferHandler.TransferSupport support) { if (!support.isDataFlavorSupported(DataFlavor.stringFlavor) || !support.isDrop()) { return false; } JTree.DropLocation dropLocation = (JTree.DropLocation) support.getDropLocation(); return dropLocation.getPath() != null; } public boolean importData(TransferHandler.TransferSupport support) { if (!canImport(support)) { return false; } JTree.DropLocation dropLocation = (JTree.DropLocation) support.getDropLocation(); TreePath path = dropLocation.getPath(); Transferable transferable = support.getTransferable(); String transferData; try { transferData = (String) transferable.getTransferData(DataFlavor.stringFlavor); } catch (IOException e) { return false; } catch (UnsupportedFlavorException e) { return false; } int childIndex = dropLocation.getChildIndex(); if (childIndex == -1) { childIndex = model.getChildCount(path.getLastPathComponent()); } DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(transferData); DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode) path.getLastPathComponent(); model.insertNodeInto(newNode, parentNode, childIndex); TreePath newPath = path.pathByAddingChild(newNode); tree.makeVisible(newPath); tree.scrollRectToVisible(tree.getPathBounds(newPath)); return true; } }); JScrollPane pane = new JScrollPane(tree); f.add(pane, BorderLayout.CENTER); tree.setDropMode(DropMode.USE_SELECTION); f.setSize(300, 400); f.setVisible(true); }
}</source>
14. Transfer both Text and Color between JTextField and JTextArea
<source lang="java">
import java.awt.Color; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.io.IOException; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.TransferHandler; import javax.swing.text.JTextComponent; public class DnDDemo2 {
public static void main(String[] args) { JFrame frame = new JFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setContentPane(new JPanel()); JTextField textField = new JTextField(25); textField.setText("Let"s swing higher"); frame.add(textField); JTextArea textArea = new JTextArea("Demonstrating\ndrag and drop"); textArea.setForeground(Color.red); frame.add(new JScrollPane(textArea)); textArea.setDragEnabled(true); textField.setDragEnabled(true); TextColorTransferHandler transferHandler = new TextColorTransferHandler(); textArea.setTransferHandler(transferHandler); textField.setTransferHandler(transferHandler); frame.pack(); frame.setVisible(true); }
} class TextColorTransferHandler extends TransferHandler {
public int getSourceActions(JComponent c) { return COPY_OR_MOVE; } protected Transferable createTransferable(JComponent component) { String text = ((JTextComponent) component).getText(); Color color = component.getForeground(); TextColor transferable = new TextColor(text, color); return transferable; } public boolean canImport(JComponent c, DataFlavor[] flavors) { return true; } public boolean importData(JComponent component, Transferable transferable) { String colorMimeType = DataFlavor.javaJVMLocalObjectMimeType + ";class=java.awt.Color"; JTextComponent textComponent = (JTextComponent) component; try { DataFlavor colorFlavor = new DataFlavor(colorMimeType); Color color = (Color) transferable.getTransferData(colorFlavor); String text = (String) transferable.getTransferData(DataFlavor.stringFlavor); textComponent.setForeground(color); textComponent.setText(text); } catch (Exception e) { e.printStackTrace(); } return true; }
} class TextColor implements Transferable {
private String text; private Color color; private DataFlavor[] flavors; public TextColor(String text, Color color) { String colorMimeType = DataFlavor.javaJVMLocalObjectMimeType + ";class=java.awt.Color"; DataFlavor colorFlavor = null; try { colorFlavor = new DataFlavor(colorMimeType); } catch (ClassNotFoundException e) { } flavors = new DataFlavor[2]; flavors[0] = DataFlavor.stringFlavor; flavors[1] = colorFlavor; this.text = text; this.color = color; } public DataFlavor[] getTransferDataFlavors() { return (DataFlavor[]) flavors.clone(); } public boolean isDataFlavorSupported(DataFlavor flavor) { for (int i = 0; i < flavors.length; i++) { if (flavor.equals(flavors[i])) { return true; } } return false; } public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException { if (flavor.equals(flavors[0])) { return text; } else if (flavor.equals(flavors[1])) { return color; } else { throw new UnsupportedFlavorException(flavor); } }
} //Reference: //Java 6 New Features: A Tutorial //by Budi Kurniawan //Brainy Software Corp. 2006 //Chapter 4 - Networking //# ISBN-10: 0975212885 //# ISBN-13: 978-0975212882</source>
14. Various drop actions
<source lang="java">
/*
* Copyright (c) 1995 - 2008 Sun Microsystems, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * - Neither the name of Sun Microsystems nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
/*
* DropDemo.java requires the following file: * ListTransferHandler.java */
import javax.swing.*; import java.awt.*; import java.awt.datatransfer.*; import java.awt.event.*;
public class DropDemo extends JPanel implements ActionListener {
private JComboBox dropCombo; private JList list; public DropDemo() { super(new GridLayout(2,1)); add(createArea()); add(createList()); } private JPanel createList() { DefaultListModel listModel = new DefaultListModel(); for (int i = 0; i < 10; i++) { listModel.addElement("List Item " + i); } list = new JList(listModel); list.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION); JScrollPane scrollPane = new JScrollPane(list); scrollPane.setPreferredSize(new Dimension(400,100)); list.setDragEnabled(true); list.setTransferHandler(new ListTransferHandler()); dropCombo = new JComboBox(new String[] {"USE_SELECTION", "ON", "INSERT", "ON_OR_INSERT"}); dropCombo.addActionListener(this); JPanel dropPanel = new JPanel(); dropPanel.add(new JLabel("List Drop Mode:")); dropPanel.add(dropCombo); JPanel panel = new JPanel(new BorderLayout()); panel.add(scrollPane, BorderLayout.CENTER); panel.add(dropPanel, BorderLayout.SOUTH); panel.setBorder(BorderFactory.createTitledBorder("List")); return panel; } private JPanel createArea() { String text = "Drag from or drop into this area.\nThe default action is MOVE;\nhold the Control key to COPY."; JTextArea area = new JTextArea(); area.setText(text); area.setDragEnabled(true); JScrollPane scrollPane = new JScrollPane(area); scrollPane.setPreferredSize(new Dimension(400,100)); JPanel panel = new JPanel(new BorderLayout()); panel.add(scrollPane, BorderLayout.CENTER); panel.setBorder(BorderFactory.createTitledBorder("Text Area")); return panel; } public void actionPerformed(ActionEvent ae) { Object val = dropCombo.getSelectedItem(); if (val == "USE_SELECTION") { list.setDropMode(DropMode.USE_SELECTION); } else if (val == "ON") { list.setDropMode(DropMode.ON); } else if (val == "INSERT") { list.setDropMode(DropMode.INSERT); } else if (val == "ON_OR_INSERT") { list.setDropMode(DropMode.ON_OR_INSERT); } } /** * Create the GUI and show it. For thread safety, * this method should be invoked from the * event-dispatching thread. */ private static void createAndShowGUI() { //Create and set up the window. JFrame frame = new JFrame("DropDemo"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //Create and set up the content pane. JComponent newContentPane = new DropDemo(); newContentPane.setOpaque(true); //content panes must be opaque frame.setContentPane(newContentPane); //Display the window. frame.pack(); frame.setVisible(true); } public static void main(String[] args) { //Schedule a job for the event-dispatching thread: //creating and showing this application"s GUI. javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { //Turn off metal"s use of bold fonts UIManager.put("swing.boldMetal", Boolean.FALSE); createAndShowGUI(); } }); }
} /*
* Copyright (c) 1995 - 2008 Sun Microsystems, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * - Neither the name of Sun Microsystems nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
/*
* ListTransferHandler.java is used by the DropDemo example. */
class ListTransferHandler extends TransferHandler {
private int[] indices = null; private int addIndex = -1; // Location where items were added private int addCount = 0; // Number of items added. public boolean canImport(TransferHandler.TransferSupport info) { // Check for String flavor if (!info.isDataFlavorSupported(DataFlavor.stringFlavor)) { return false; } return true; } protected Transferable createTransferable(JComponent c) { return new StringSelection(exportString(c)); } public int getSourceActions(JComponent c) { return TransferHandler.COPY_OR_MOVE; } public boolean importData(TransferHandler.TransferSupport info) { if (!info.isDrop()) { return false; } JList list = (JList) info.getComponent(); DefaultListModel listModel = (DefaultListModel) list.getModel(); JList.DropLocation dl = (JList.DropLocation) info.getDropLocation(); int index = dl.getIndex(); boolean insert = dl.isInsert(); // Get the string that is being dropped. Transferable t = info.getTransferable(); String data; try { data = (String) t.getTransferData(DataFlavor.stringFlavor); } catch (Exception e) { return false; } // Perform the actual import. if (insert) { listModel.add(index, data); } else { listModel.set(index, data); } return true; } protected void exportDone(JComponent c, Transferable data, int action) { cleanup(c, action == TransferHandler.MOVE); } // Bundle up the selected items in the list // as a single string, for export. protected String exportString(JComponent c) { JList list = (JList) c; indices = list.getSelectedIndices(); Object[] values = list.getSelectedValues(); StringBuffer buff = new StringBuffer(); for (int i = 0; i < values.length; i++) { Object val = values[i]; buff.append(val == null ? "" : val.toString()); if (i != values.length - 1) { buff.append("\n"); } } return buff.toString(); } // Take the incoming string and wherever there is a // newline, break it into a separate item in the list. protected void importString(JComponent c, String str) { JList target = (JList) c; DefaultListModel listModel = (DefaultListModel) target.getModel(); int index = target.getSelectedIndex(); // Prevent the user from dropping data back on itself. // For example, if the user is moving items #4,#5,#6 and #7 and // attempts to insert the items after item #5, this would // be problematic when removing the original items. // So this is not allowed. if (indices != null && index >= indices[0] - 1 && index <= indices[indices.length - 1]) { indices = null; return; } int max = listModel.getSize(); if (index < 0) { index = max; } else { index++; if (index > max) { index = max; } } addIndex = index; String[] values = str.split("\n"); addCount = values.length; for (int i = 0; i < values.length; i++) { listModel.add(index++, values[i]); } } // If the remove argument is true, the drop has been // successful and it"s time to remove the selected items // from the list. If the remove argument is false, it // was a Copy operation and the original list is left // intact. protected void cleanup(JComponent c, boolean remove) { if (remove && indices != null) { JList source = (JList) c; DefaultListModel model = (DefaultListModel) source.getModel(); // If we are moving items around in the same list, we // need to adjust the indices accordingly, since those // after the insertion point have moved. if (addCount > 0) { for (int i = 0; i < indices.length; i++) { if (indices[i] > addIndex) { indices[i] += addCount; } } } for (int i = indices.length - 1; i >= 0; i--) { model.remove(indices[i]); } } indices = null; addCount = 0; addIndex = -1; }
}</source>