我正在尝试设置代码,以便用户可以从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();
}
});
}
}
答案 0 :(得分:6)
//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(); }
});
}
}
答案 1 :(得分:1)
为了让TransferHandler显示自定义图像(发生拖动时),您必须创建一个TransferHandler的子类,并使用以下函数覆盖它:
public int getSourceActions(JComponent)
- 它必须返回源支持的操作(从中启动拖动的JComponent),如果启动时拖动请求的操作(参见5)不匹配,则它将无效。 / LI>
public Transferable createTransferable(JComponent c)
- TransferHandler必须返回Transferable对象,如果返回null,则不会启动拖动。public Image getDragImage()
需要重新启动想要的图片,或者应该在自定义TransferHandler的实例上调用setDragImage()
要开始拖动,请使用以下方法覆盖/扩展MouseMotionListener:
public void mouseDragged(MouseEvent e){
JComponent jc = (JComponent)e.getSource();
jc.getTransferHandler().exportAsDrag(jc, e,TransferHandler.COPY);
}
并将JComponent TransferHandler和MouseMotionListener设置为:
myJComponent.setTransferHandler(new myCustomTransferHandler());
myJComponent.addMouseMotionListener(new myCustomMouseMotionListener());
package test;
import javax.swing.*;
import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import javax.imageio.ImageIO;
public class DragTest{
Image dragImage;
public static void main(String[] args){
new DragTest();
}
public DragTest(){
try{
dragImage = javax.imageio.ImageIO.read( new java.net.URL(
"https://www.icon2s.com/wp-content/uploads/2013/07/black-white-metro-file-icon.png"));
//dragImage = ImageIO.read(new java.io.File("icon.png")); //can be used to read image from file
}catch(java.io.IOException e1){
e1.printStackTrace();
return;
}
dragImage = dragImage.getScaledInstance(64, 64, Image.SCALE_DEFAULT); //scaling the image
JFrame frame = new JFrame();
frame.setLayout(null);
frame.setSize(500,500); frame.setLocationRelativeTo(null); //size and location
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
MyJComponent myJC = new MyJComponent();
myJC.setBounds(50,50,100,100);
myJC.addMouseMotionListener(new MouseMotionListener(){
@Override
public void mouseDragged(MouseEvent e){
JComponent src = (JComponent)e.getSource();
src.getTransferHandler().exportAsDrag(src, e, TransferHandler.COPY); //try to export with the copy action - TransferHandler should support copy
}
@Override
public void mouseMoved(MouseEvent e){}
});
myJC.setTransferHandler(new TransferHandler(){
@Override public Image getDragImage(){ return(dragImage);}
@Override public int getSourceActions(JComponent c){
return(COPY_OR_MOVE); //supporting both copy and move
}
@Override public Transferable createTransferable(JComponent c){
return(new Transferable(){
@Override
public boolean isDataFlavorSupported(DataFlavor flavor){
return false;
}
@Override
public DataFlavor[] getTransferDataFlavors(){
return null;
}
@Override
public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, java.io.IOException {
return null;
}
});
}
});
frame.add(myJC);
frame.setVisible(true);
}
private class MyJComponent extends JComponent{
@Override
public void paintComponent(Graphics g){
g.setColor(Color.RED);
g.fillRect(0, 0, getWidth(), getHeight());
}
}
}