java 使用 TransferHandler 拖动 JLabel(拖放)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11460704/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Dragging a JLabel with a TransferHandler (Drag and Drop)
提问by mainstringargs
I am using a TransferHandler to pass data from a JPanel to a JTextArea as a JLabel (Click somewhere in the left panel to create the JLabel to drag)
我正在使用 TransferHandler 将数据从 JPanel 传递到 JTextArea 作为 JLabel(单击左侧面板中的某处以创建要拖动的 JLabel)
The transfer of the data works fine, but I'd like to also "show" the JLabel as its being dragged along with the mouse pointer.
数据的传输工作正常,但我还想在 JLabel 与鼠标指针一起拖动时“显示”它。
If you comment out
如果你注释掉
dropLabel.setTransferHandler(new TransferHandler("text"));
dropLabel.getTransferHandler().exportAsDrag(dropLabel, e,
TransferHandler.COPY);
you will see how I want it to look. (but of course then the data won't be transferred).
你会看到我想要的样子。(但当然数据不会被传输)。
How can I get both the transfer to work and the JLabel to follow the mouse cursor?
我怎样才能让传输工作和 JLabel 跟随鼠标光标?
Here is the code:
这是代码:
import java.awt.*;
import java.awt.datatransfer.Transferable;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.Border;
public class DragTest extends JFrame implements MouseMotionListener,
MouseListener {
private JPanel leftPanel = new JPanel(null);
private JPanel rightPanel = new JPanel(null);
private JLabel dragLabel = new JLabel("drop");
private final JWindow window = new JWindow();
JLabel dropLabel;
public DragTest() {
this.setLayout(new GridLayout(1, 2));
leftPanel.setBorder(BorderFactory.createLineBorder(Color.black));
rightPanel.setBorder(BorderFactory.createLineBorder(Color.black));
this.add(leftPanel);
this.add(rightPanel);
leftPanel.addMouseListener(this);
leftPanel.addMouseMotionListener(this);
JTextArea area = new JTextArea();
rightPanel.setLayout(new GridLayout(1, 1));
rightPanel.add(area);
dragLabel.setFont(new Font("Serif", Font.BOLD, 48));
}
@Override
public void mousePressed(MouseEvent e) {
dropLabel = new JLabel("drop");
Dimension labelSize = dropLabel.getPreferredSize();
dropLabel.setSize(labelSize);
int x = e.getX() - labelSize.width / 2;
int y = e.getY() - labelSize.height / 2;
dropLabel.setLocation(x, y);
leftPanel.add(dropLabel);
dropLabel.setTransferHandler(new TransferHandler("text"));
dropLabel.getTransferHandler().exportAsDrag(dropLabel, e,
TransferHandler.COPY);
repaint();
}
@Override
public void mouseDragged(MouseEvent me) {
dragLabel = new JLabel("drop");
dragLabel.setFont(new Font("Serif", Font.BOLD, 48));
int x = me.getPoint().x;
int y = me.getPoint().y;
window.add(dragLabel);
window.pack();
Point pt = new Point(x, y);
Component c = (Component) me.getSource();
SwingUtilities.convertPointToScreen(pt, c);
window.setLocation(pt);
window.setVisible(true);
repaint();
}
@Override
public void mouseMoved(MouseEvent e) {
}
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
// leftPanel.remove(dropLabel);
window.remove(dragLabel);
window.setVisible(false);
repaint();
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
public static void main(String[] args) {
DragTest frame = new DragTest();
frame.setVisible(true);
frame.setSize(600, 400);
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
回答by aterai
Another example:
另一个例子:
Edit: Fix a blinking cursor
编辑:修复闪烁的光标
import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.dnd.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import javax.activation.*;
import javax.swing.*;
import javax.swing.text.*;
public class DragTest3 {
public JComponent makeUI() {
DragPanel p1 = new DragPanel();
p1.setBorder(BorderFactory.createLineBorder(Color.BLACK));
p1.add(new JLabel(UIManager.getIcon("OptionPane.warningIcon")));
p1.add(new JLabel(UIManager.getIcon("OptionPane.errorIcon")));
p1.add(new JLabel("Label1"));
p1.add(new JLabel("Label2"));
MouseListener handler = new Handler();
p1.addMouseListener(handler);
LabelTransferHandler th = new LabelTransferHandler();
p1.setTransferHandler(th);
JPanel p = new JPanel(new GridLayout(1,2));
p.add(p1);
DragPanel p2 = new DragPanel();
p2.setBorder(BorderFactory.createLineBorder(Color.BLACK));
p2.addMouseListener(handler);
p2.setTransferHandler(th);
p.add(p2);
JPanel panel = new JPanel(new GridLayout(2,1));
panel.add(p);
panel.add(new JScrollPane(new JTextArea()));
return panel;
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override public void run() {
createAndShowGUI();
}
});
}
public static void createAndShowGUI() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.getContentPane().add(new DragTest3().makeUI());
f.setSize(320, 240);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
class DragPanel extends JPanel {
public DragPanel() {
super();
}
public JLabel draggingLabel;
}
class Handler extends MouseAdapter {
@Override public void mousePressed(MouseEvent e) {
DragPanel p = (DragPanel)e.getSource();
Component c = SwingUtilities.getDeepestComponentAt(p, e.getX(), e.getY());
if(c!=null && c instanceof JLabel) {
p.draggingLabel = (JLabel)c;
p.getTransferHandler().exportAsDrag(p, e, TransferHandler.MOVE);
}
}
}
class LabelTransferHandler extends TransferHandler {
private final DataFlavor localObjectFlavor;
private final JLabel label = new JLabel() {
@Override public boolean contains(int x, int y) {
return false;
}
};
private final JWindow window = new JWindow();
public LabelTransferHandler() {
System.out.println("LabelTransferHandler");
localObjectFlavor = new ActivationDataFlavor(
DragPanel.class, DataFlavor.javaJVMLocalObjectMimeType, "JLabel");
window.add(label);
window.setAlwaysOnTop(true);
window.setBackground(new Color(0,true));
DragSource.getDefaultDragSource().addDragSourceMotionListener(
new DragSourceMotionListener() {
@Override public void dragMouseMoved(DragSourceDragEvent dsde) {
Point pt = dsde.getLocation();
pt.translate(5, 5); // offset
window.setLocation(pt);
}
});
}
@Override protected Transferable createTransferable(JComponent c) {
System.out.println("createTransferable");
DragPanel p = (DragPanel)c;
JLabel l = p.draggingLabel;
String text = l.getText();
//TEST
//if(text==null) {
// text = l.getIcon().toString();
//}
//return new StringSelection(text+"\n");
final DataHandler dh = new DataHandler(c, localObjectFlavor.getMimeType());
if(text==null) return dh;
final StringSelection ss = new StringSelection(text+"\n");
return new Transferable() {
@Override public DataFlavor[] getTransferDataFlavors() {
ArrayList<DataFlavor> list = new ArrayList<>();
for(DataFlavor f:ss.getTransferDataFlavors()) {
list.add(f);
}
for(DataFlavor f:dh.getTransferDataFlavors()) {
list.add(f);
}
return list.toArray(dh.getTransferDataFlavors());
}
public boolean isDataFlavorSupported(DataFlavor flavor) {
for (DataFlavor f: getTransferDataFlavors()) {
if (flavor.equals(f)) {
return true;
}
}
return false;
}
public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
if(flavor.equals(localObjectFlavor)) {
return dh.getTransferData(flavor);
} else {
return ss.getTransferData(flavor);
}
}
};
}
@Override public boolean canImport(TransferSupport support) {
if(!support.isDrop()) {
return false;
}
return true;
}
@Override public int getSourceActions(JComponent c) {
System.out.println("getSourceActions");
DragPanel p = (DragPanel)c;
label.setIcon(p.draggingLabel.getIcon());
label.setText(p.draggingLabel.getText());
window.pack();
Point pt = p.draggingLabel.getLocation();
SwingUtilities.convertPointToScreen(pt, p);
window.setLocation(pt);
window.setVisible(true);
return MOVE;
}
@Override public boolean importData(TransferSupport support) {
System.out.println("importData");
if(!canImport(support)) return false;
DragPanel target = (DragPanel)support.getComponent();
try {
DragPanel src = (DragPanel)support.getTransferable().getTransferData(localObjectFlavor);
JLabel l = new JLabel();
l.setIcon(src.draggingLabel.getIcon());
l.setText(src.draggingLabel.getText());
target.add(l);
target.revalidate();
return true;
} catch(UnsupportedFlavorException ufe) {
ufe.printStackTrace();
} catch(java.io.IOException ioe) {
ioe.printStackTrace();
}
return false;
}
@Override protected void exportDone(JComponent c, Transferable data, int action) {
System.out.println("exportDone");
DragPanel src = (DragPanel)c;
if(action == TransferHandler.MOVE) {
src.remove(src.draggingLabel);
src.revalidate();
src.repaint();
}
src.draggingLabel = null;
window.setVisible(false);
}
}
回答by MadProgrammer
UPDATE: Unfortunately, you're using a TransferHandler
.
更新:不幸的是,您正在使用TransferHandler
.
The last time I played around with the TransferHandler
API (back around 6.10/6.12) there was a bug in the code which ignored the transfer image. It actually set it to null. This may have been fixed in later updates, but I've not checked recently.
上次我玩TransferHandler
API 时(大约在 6.10/6.12 左右),代码中有一个错误,它忽略了传输图像。它实际上将其设置为空。这可能已在以后的更新中修复,但我最近没有检查过。
After much digging, I've found that the default implementation of the TransferHandler ignores the "getVisualRepresentation(Transferable t)" method. Great isn't it.
经过大量挖掘,我发现 TransferHandler 的默认实现忽略了“getVisualRepresentation(Transferable t)”方法。很棒不是吗。
I did some digging and the class makes use of a bunch of "private" inner classes to handle the workings of the DnD process, making it next to near impossible to simply change the implementation without having to rewrite the whole thing.
我做了一些挖掘,该类使用一堆“私有”内部类来处理 DnD 过程的工作,这使得几乎不可能简单地更改实现而不必重写整个过程。
Basically, the DragSource
allows you to pass in a image it can use (as to if this works is another question), but it's hidden inside a private DragHandler
class. Thanks Sun.
基本上,它DragSource
允许您传入它可以使用的图像(至于这是否有效是另一个问题),但它隐藏在私有DragHandler
类中。谢谢孙。
回答by Code Poster
I used this code and made some modifications. I am reposting it to SO as per the TOS.
我使用了这段代码并做了一些修改。我根据 TOS 将其转发给 SO。
import java.awt.Color;
import java.awt.Point;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DragSource;
import java.awt.dnd.DragSourceDragEvent;
import java.awt.dnd.DragSourceMotionListener;
import java.io.IOException;
import java.util.ArrayList;
import javax.activation.ActivationDataFlavor;
import javax.activation.DataHandler;
import javax.swing.*;
@SuppressWarnings("serial")
public class LabelTransferHandler extends TransferHandler {
private final DataFlavor localObjectFlavor;
private final DeviceAssignments root;
private final JLabel label = new JLabel() {
@Override public boolean contains(int x, int y) {
return false;
}
};
private final JWindow window = new JWindow();
public LabelTransferHandler(DeviceAssignments root) {
this.root = root;
localObjectFlavor = new ActivationDataFlavor(
LabelDragScrollPane.class, DataFlavor.javaJVMLocalObjectMimeType, "JLabel");
window.add(label);
window.setAlwaysOnTop(true);
window.setBackground(new Color(0,true));
DragSource.getDefaultDragSource().addDragSourceMotionListener(
new DragSourceMotionListener() {
@Override public void dragMouseMoved(DragSourceDragEvent dsde) {
Point pt = dsde.getLocation();
pt.translate(5, 5); // offset
window.setLocation(pt);
}
}
);
}
@Override protected Transferable createTransferable(JComponent c) {
LabelDragScrollPane p = (LabelDragScrollPane)c;
MacLabel l = p.draggingLabel;
String text = l.getMac();
final DataHandler dh = new DataHandler(c, localObjectFlavor.getMimeType());
if(text==null) return dh;
final StringSelection ss = new StringSelection(text+"\n");
return new Transferable() {
@Override public DataFlavor[] getTransferDataFlavors() {
ArrayList<DataFlavor> list = new ArrayList<DataFlavor>();
for(DataFlavor f:ss.getTransferDataFlavors()) {
list.add(f);
}
for(DataFlavor f:dh.getTransferDataFlavors()) {
list.add(f);
}
return list.toArray(dh.getTransferDataFlavors());
}
public boolean isDataFlavorSupported(DataFlavor flavor) {
for (DataFlavor f: getTransferDataFlavors()) {
if (flavor.equals(f)) {
return true;
}
}
return false;
}
public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
if(flavor.equals(localObjectFlavor)) {
return dh.getTransferData(flavor);
} else {
return ss.getTransferData(flavor);
}
}
};
}
@Override public boolean canImport(TransferSupport support) {
if(!support.isDrop()) {
return false;
}
return true;
}
@Override public int getSourceActions(JComponent c) {
LabelDragScrollPane p = (LabelDragScrollPane)c;
label.setBorder(p.draggingLabel.getBorder());
label.setText(p.draggingLabel.getMac());
label.setPreferredSize(p.draggingLabel.getPreferredSize());
window.pack();
Point pt = p.draggingLabel.getLocation();
SwingUtilities.convertPointToScreen(pt, p);
window.setLocation(pt);
window.setVisible(true);
return MOVE;
}
@Override public boolean importData(TransferSupport support) {
if(!canImport(support)) return false;
JButton target = (JButton)support.getComponent();
try {
LabelDragScrollPane src = (LabelDragScrollPane)support.getTransferable().getTransferData(localObjectFlavor);
target.setText(src.draggingLabel.getMac());
return true;
} catch(UnsupportedFlavorException ufe) {
ufe.printStackTrace();
} catch(java.io.IOException ioe) {
ioe.printStackTrace();
}
return false;
}
@Override protected void exportDone(JComponent c, Transferable data, int action) {
LabelDragScrollPane src = (LabelDragScrollPane)c;
if(action == TransferHandler.MOVE) {
root.updateNodeIdPanel();
}
src.draggingLabel = null;
window.setVisible(false);
}
}