我正在尝试设置代码,以便用户可以从JTable拖动到JList,并使用TransferHandler中的Java 7函数setDragImage自定义拖动图像。我在Java教程网站上获取了一个示例,在该示例中,他们教了有关Drag n Drop的知识,然后添加了“setDragImage”代码。但是,它不起作用。请参见下面的代码,并在importData函数中找到setDragImage()行。为什么不起作用?

/*
 * Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved.
 *
 */

import java.util.*;
import java.awt.*;
import java.awt.event.*;
import java.text.*;
import java.awt.datatransfer.*;
import java.awt.image.BufferedImage;

import javax.swing.*;
import javax.swing.text.*;
import javax.swing.tree.*;
import javax.swing.table.*;

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 Image getDragImage() {
                return null;
            }

            @Override
            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 BufferedImage makeImageFromString(String s) {
                int width = 100;
                int height = 40;
                BufferedImage br = new BufferedImage(width,height,BufferedImage.TYPE_INT_ARGB);
                Graphics g = br.getGraphics();
                g.drawString(s, 0, 0);
                //g.fillRect(0, 0, width, height);
                System.out.println("made image from " + s);
                return br;
            }

            @Override
            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; }

                //HERE IS THE CODE TO SET THE DRAG IMAGE
                this.setDragImage(makeImageFromString(data));

                // 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;
            }

            @Override
            public int getSourceActions(JComponent c) {
                return COPY;
            }

            @Override
            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();
            }
        });
    }
}

最佳答案

如kleopatra所说,删除getDragImage(){return null;

  • 将TransferHandler#setDragImage(...)从importData(...)移到getSourceActions(...)
  • 修复您的makeImageFromString(...)

  • //As kleopatra says,
    //public Image getDragImage() {
    //    return null;
    //}
    public boolean importData(TransferHandler.TransferSupport info) {
        //...
        //HERE IS THE CODE TO SET THE DRAG IMAGE
        //XXX: this.setDragImage(makeImageFromString(data));
        //...
    }
    @Override public int getSourceActions(JComponent c) {
      System.out.println("getSourceActions");
      this.setDragImage(makeImageFromString(c));
      return COPY;
    }
    
    FontRenderContext frc = new FontRenderContext(null, true, true);
    JPanel p = new JPanel();
    public BufferedImage makeImageFromString(JComponent c) {
      int width = 100;
      int height = 40;
      BufferedImage br = new BufferedImage(width,height,BufferedImage.TYPE_INT_ARGB);
      Graphics g = br.getGraphics();
      g.setColor(Color.RED);
      g.fillRect(0, 0, width, height);
    
    //*
      JList l = (JList)c;
      ListCellRenderer r = l.getCellRenderer();
      Component comp = r.getListCellRendererComponent(
          l, l.getSelectedValue(), l.getSelectedIndex(), false, false);
      SwingUtilities.paintComponent(g, comp, p, 0, 0, width, height);
    /*/
      String s = "aaaa";
      Rectangle rect = c.getFont().getStringBounds(s, frc).getBounds();
      int tx = (width  - rect.width)/2  - rect.x;
      int ty = (height - rect.height)/2 - rect.y;
      g.setColor(Color.BLACK);
      g.drawString(s, tx, ty);
      System.out.println("made image from " + s);
    //*/
      g.dispose();
      return br;
    }
    

    注意:TransferHandler#setDragImage(java.awt.Image) (Java Platform SE 7 )

    添加SSCCE:如何使用TransferHandler#setDragImage(...)方法。
    import java.util.*;
    import java.awt.*;
    import java.awt.image.*;
    import java.awt.datatransfer.*;
    import javax.swing.*;
    public class BasicDnD {
      private JList list;
      public JList makeList() {
        DefaultListModel<String> m = new DefaultListModel<>();
        m.addElement("Martha Washington");
        m.addElement("Abigail Adams");
        m.addElement("Martha Randolph");
        list = new JList<String>(m);
        list.setTransferHandler(new TransferHandler() {
          @Override public boolean canImport(TransferHandler.TransferSupport info) {
            if (!info.isDataFlavorSupported(DataFlavor.stringFlavor)) {
              return false;
            }
            JList.DropLocation dl = (JList.DropLocation)info.getDropLocation();
            if (dl.getIndex() == -1) {
              return false;
            }
            return true;
          }
          @Override public int getSourceActions(JComponent c) {
            setDragImage(makeImageFromString(c));
            return COPY;
          }
          private final JPanel p = new JPanel();
          private BufferedImage br;
          private int width, height;
          private BufferedImage makeImageFromString(JComponent src) {
            JList l = (JList)src;
            int idx = l.getSelectedIndex();
            Rectangle rect = list.getCellBounds(idx,idx);
            if(rect==null) return null;
            if(br==null || rect.width!=width || rect.height!=height) {
              width  = rect.width;
              height = rect.height;
              br = new BufferedImage(width,height,BufferedImage.TYPE_INT_ARGB);
            }
            Component c = l.getCellRenderer().getListCellRendererComponent(
                l, l.getSelectedValue(), idx, false, false);
            Graphics g = br.getGraphics();
            g.clearRect(0,0,width,height);
            SwingUtilities.paintComponent(g, c, p, 0, 0, width, height);
            g.dispose();
            return br;
          }
          @Override 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);
        list.setDragEnabled(true);
        return list;
      }
      public JComponent makeUI() {
        JPanel panel = new JPanel(new GridLayout(2,1));
        JTextArea textArea = new JTextArea("Drag here from JList!");
        panel.add(new JScrollPane(textArea));
        panel.add(new JScrollPane(makeList()));
        return panel;
      }
      private static void createAndShowGUI() {
        JFrame f = new JFrame("BasicDnD");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setContentPane(new BasicDnD().makeUI());
        f.setSize(320, 320);
        f.setLocationRelativeTo(null);
        f.setVisible(true);
      }
      public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
          @Override public void run() { createAndShowGUI(); }
        });
      }
    }
    

    10-05 21:51