使用TransferHandler拖动JLabel(拖放)

时间:2012-07-12 21:07:31

标签: java swing drag-and-drop jpanel

我正在使用TransferHandler将数据从JPanel传递到JTextArea作为JLabel(单击左侧面板中的某个位置以创建要拖动的JLabel)

数据的传输工作正常,但我也想“显示”JLabel与鼠标指针一起被拖动。

如果你发表评论

dropLabel.setTransferHandler(new TransferHandler("text"));

dropLabel.getTransferHandler().exportAsDrag(dropLabel, e,
            TransferHandler.COPY);

你会看到我希望它看起来如何。 (但当然数据不会被转移)。

如何让传输工作和JLabel跟随鼠标光标?

以下是代码:

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

3 个答案:

答案 0 :(得分:9)

另一个例子:

enter image description here

编辑:修复闪烁的光标

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

答案 1 :(得分:3)

更新:不幸的是,您使用的是TransferHandler

上次我使用TransferHandler API(回到6.10 / 6.12)时,代码中存在一个忽略传输图像的错误。它实际上将其设置为null。这可能已在以后的更新中修复,但我最近没有检查过。

经过多次挖掘,我发现TransferHandler的默认实现忽略了“getVisualRepresentation(Transferable t)”方法。好不是吧。

我做了一些挖掘,并且该类使用了一堆“私有”内部类来处理DnD进程的工作,使得几乎不可能简单地改变实现而不必重写整个事物。 / p>

基本上,DragSource允许您传入可以使用的图像(如果这是另一个问题),但它隐藏在私有DragHandler类中。谢谢Sun。

答案 2 :(得分:-2)

我使用了这段代码并进行了一些修改。我按照服务条款将其转发给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);
    }
}