2012-07-12 57 views
6

estoy usando un TransferHandler para pasar datos de un JPanel a un JTextArea como JLabel (Haga clic en alguna parte en el panel izquierdo para crear el JLabel para arrastrar)arrastrar un JLabel con un TransferHandler (arrastrar y soltar)

El la transferencia de los datos funciona bien, pero me gustaría también "mostrar" el JLabel mientras se arrastra junto con el puntero del mouse.

Si en comentario

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

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

verá cómo quiero que se vea. (pero por supuesto, entonces los datos no serán transferidos).

¿Cómo puedo hacer que la transferencia funcione y que JLabel siga el cursor del mouse?

Aquí está el código:

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

Respuesta

9

Otro ejemplo:

enter image description here

Editar: fijar un cursor parpadeante

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

Eso es trampa;) – MadProgrammer

+0

@MadProgrammer Creo que sí, también :) – aterai

+0

Ah sí, pero es un buen truco;) – MadProgrammer

3

ACTUALIZACIÓN: Por desgracia, estás usando un TransferHandler.

La última vez que jugué con la API TransferHandler (alrededor de 6.10/6.12), había un error en el código que ignoraba la imagen de transferencia. En realidad lo estableció en nulo. Esto puede haberse solucionado en actualizaciones posteriores, pero no lo he comprobado recientemente.

Después de excavar mucho, descubrí que la implementación predeterminada de TransferHandler ignora el método "getVisualRepresentation (Transferible t)". Genial no es eso.

Hice algunas excavaciones y la clase hace uso de un montón de clases internas "privadas" para manejar el funcionamiento del proceso DnD, por lo que es casi imposible simplemente cambiar la implementación sin tener que volver a escribir todo.

Básicamente, el DragSource le permite pasar una imagen que puede usar (si esto funciona es otra pregunta), pero está escondida dentro de una clase privada DragHandler. Gracias Sun.

+0

y tenía un aspecto un intento de reescribir la empuñadura de transferencia, pero no hay mucho código privado paquete que no es sólo una tarea sencilla para tratar – MadProgrammer

+0

Probé un proceso Molestar "manual" y el método "starDrag" no lo hace use la imagen de arrastre que proporcioné en Windows 7 (creo que Mac puede hacerlo) ... es posible que desee consultar http://rabbit-hole.blogspot.com.au/2006/05/my-drag-image- es-mejor que-yours.html para obtener más información – MadProgrammer

-2

utilicé este código y hecho algunas modificaciones. Lo vuelvo a publicar en SO según el 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); 
    } 
} 
+0

Esto no parece ser una nueva respuesta a la pregunta y probablemente se eliminará. Si está reutilizando el código y está preocupado por la licencia de CC, entonces necesita preguntarle al autor original acerca de las licencias adicionales o publicar la atribución en el lugar donde la está usando, no aquí. –

+0

Haz lo que quieras con él.Seguí los Términos de uso para el sitio web. Mi conciencia está limpia. –