Drag and Drop JLabel with TransferHandler (drag and drop)

I use TransferHandler to transfer data from JPanel to JTextArea as JLabel (click anywhere in the left pane to create a JLabel drag and drop)

Data transfer is working fine, but I would also like to “show” JLabel as it is being dragged along with the mouse pointer.

If you comment

dropLabel.setTransferHandler(new TransferHandler("text")); dropLabel.getTransferHandler().exportAsDrag(dropLabel, e, TransferHandler.COPY); 

You will see how I want it to look. (but, of course, the data will not be transmitted).

How can I get both the transfer to work and JLabel to follow the mouse pointer?

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); } } 
+6
source share
3 answers

Another example:

enter image description here

Edit: fix 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); } } 
+9
source

UPDATE: Unfortunately, you are using TransferHandler .

The last time I played with the TransferHandler API (back around 6.10 / 6.12), an error occurred in the code that ignored the transfer image. In fact, it sets to null. This may have been fixed in subsequent updates, but I have not tested it recently.

After searching repeatedly, I found that the TransferHandler implementation by default ignores the getVisualRepresentation (Transferable t) method. Great, not like that.

I did something, and the class uses a bunch of "private" inner classes to handle the work of the DnD process, which makes it almost impossible to just change the implementation without rewriting it all.

Basically, DragSource allows DragSource to transfer an image that it can use (as for this, this is another question), but it is hidden inside the private DragHandler class. Thanks sun.

+3
source

I used this code and made some changes. I port it to SO according to TOS.

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

Source: https://habr.com/ru/post/920372/


All Articles