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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 05:11:51  来源:igfitidea点击:

Dragging a JLabel with a TransferHandler (Drag and Drop)

javaswingdrag-and-dropjpanel

提问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:

另一个例子:

enter image description here

在此处输入图片说明

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 TransferHandlerAPI (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.

上次我玩TransferHandlerAPI 时(大约在 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 DragSourceallows you to pass in a image it can use (as to if this works is another question), but it's hidden inside a private DragHandlerclass. 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);
    }
}