Drag and Drop: 3 Fragen

Status
Nicht offen für weitere Antworten.

max60watt

Mitglied
Hallo zusammen,
nachdem ich einige Zeit gegoogelt und auch in diesem Forum geblättert habe, ist es mir gelungen ein Drag und Drop mit dragGestureRecognized aufzubauen (ein funktionierendes DnD mit eigenem TransferHandler wäre der nächste Schritt).
Das Transfer-Objekt ist kein Standard Objekt, sondern ein selbstgebautes JPanel mit JTextField, JLabel+Icon und einer JCheckBox.

Hier erstmal das kleine KSKB (naja, es sind fünf Klassen)

Das Panel das per DnD verschoben werden soll:

Code:
import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.dnd.*;
import java.awt.image.*;
import javax.swing.*;
import javax.swing.border.*;

public class MovePanel extends JPanel implements DragGestureListener, DragSourceListener{
  JTextField textField = new JTextField();
  JLabel imageLabel = new JLabel();
  JCheckBox checkbox = new JCheckBox("Check Box" ,true);
  int id;
  String string;
  Color color;
  private DragSource dragSource;
//------------------------------------------------------------------------------------------------
  public MovePanel(String s, Color c, int x, int y, int i){
    string = s;
    color = c;
    id = i;
    setLayout(null);
    setLocation(x, y);
    setSize(180,160);
    setBackground(Color.WHITE);
    setBorder(new LineBorder(Color.black));

    imageLabel.setBounds(10,10,160,120);
    imageLabel.setIcon(new ImageIcon(createImage(string, color)));
    textField.setText(string);
    textField.setBounds(10,137,100,19);
    checkbox.setBounds(142,137,18,19);

    add(imageLabel);
    add(textField);
    add(checkbox);

    dragSource = new DragSource();
    dragSource.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_COPY_OR_MOVE, this);
  }
//------------------------------------------------------------------------------------------------
  public void setMovePanelLocation(int x,int y){
    setLocation(x,y);
  }
//------------------------------------------------------------------------------------------------
  public void dragGestureRecognized(DragGestureEvent dge){
    Transferable t = new PanelTransferable(this);
    dragSource.startDrag(dge, DragSource.DefaultCopyDrop, t, this);
  }
//------------------------------------------------------------------------------------------------
  public void dragEnter(DragSourceDragEvent dsde){}
//------------------------------------------------------------------------------------------------
  public void dragOver(DragSourceDragEvent dsde){}
//------------------------------------------------------------------------------------------------
  public void dropActionChanged(DragSourceDragEvent dsde){}
//------------------------------------------------------------------------------------------------
  public void dragDropEnd(DragSourceDropEvent dsde) {}
//------------------------------------------------------------------------------------------------
  public void dragExit(DragSourceEvent dsde) {}
//------------------------------------------------------------------------------------------------
  public BufferedImage createImage(String s, Color c){
    BufferedImage bufferedImage = new BufferedImage(162, 120, BufferedImage.TYPE_3BYTE_BGR);
    Graphics g = bufferedImage.createGraphics();

    g.setColor(c);
    g.fillRect(0,0,160,120);
    g.setColor(Color.BLUE);
    g.drawString(s, 10,20);
    return bufferedImage;
  }
//------------------------------------------------------------------------------------------------
}

Das passende Transferable dazu:

Code:
import java.awt.datatransfer.*;
import java.io.*;
//http://www.java2s.com/Code/Java/Swing-JFC/JLabelDragSource.htm
class PanelTransferable implements Transferable {
  MovePanel movePanel;
  public static final DataFlavor panelFlavor = new DataFlavor(MovePanel.class, "Move Panel");
  private static final DataFlavor[] flavors = new DataFlavor[] {
    panelFlavor
  };
//------------------------------------------------------------------------------------------------
  public PanelTransferable(MovePanel m) {
    this.movePanel = m;
  }
//------------------------------------------------------------------------------------------------
  public DataFlavor[] getTransferDataFlavors() {
    return flavors;
  }
//------------------------------------------------------------------------------------------------
  public boolean isDataFlavorSupported(DataFlavor fl) {
    for (int i = 0; i < flavors.length; i++) {
      if (fl.equals(flavors[i])) {
        return true;
      }
    }
  System.out.println("no Flavor");
  return false;
  }
//------------------------------------------------------------------------------------------------
  public Object getTransferData(DataFlavor fl) {
    if (!isDataFlavorSupported(fl)) {
      return null;
    }

    if (fl.equals(panelFlavor)) {
      return movePanel;
    }
    else{
      return null;
    }

  }
//------------------------------------------------------------------------------------------------
}

Das Quellframe zum draggen:

Code:
import java.awt.*;
import javax.swing.*;

//http://www.dpunkt.de/java/Programmieren_mit_Java/Oberflaechenprogrammierung/69.html

public class DragFrame extends JFrame{
MovePanel myPanel01 = new MovePanel("Eins", Color.red,10,10,1);
MovePanel myPanel02 = new MovePanel("Zwei", Color.green,200,10,2);
//------------------------------------------------------------------------------------------------
  public DragFrame(){
    super("Drag Frame");
    setLayout(null);
    add(myPanel01);
    add(myPanel02);
  }
//------------------------------------------------------------------------------------------------
  //Diese Methode aufrufen, wenn MOVE - siehe Frage 3
  public void rmPanel(){
    // do something
  }
//------------------------------------------------------------------------------------------------
  public static void main(String args[]){
  DragFrame app = new DragFrame();
    app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    app.setBounds(10,10,400,260);
    app.setVisible(true);
  }
//------------------------------------------------------------------------------------------------
}

Das Zielframe zum droppen:

Code:
import java.awt.dnd.*;
import javax.swing.*;

public class DropFrame extends JFrame{
  DropTarget target = new DropTarget(this, new DropObject(this));
//------------------------------------------------------------------------------------------------
  public DropFrame(){
    super("Drop Frame");
    this.setLayout(null);
    setDropTarget(target);
  }
//------------------------------------------------------------------------------------------------
  public void setPanel(MovePanel m){
    MovePanel movePanel = m;
    // hier Mouseposition ermitteln - siehe Frage 1
    //movePanel.setMovePanelLocation(10,30);
    add(movePanel);
    repaint();
  }
//------------------------------------------------------------------------------------------------
  public static void main(String args[]){
  DropFrame app = new DropFrame();
    app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    app.setBounds(420,10,400,260);
    app.setVisible(true);
  }
//------------------------------------------------------------------------------------------------
}

Und schliesslich ein DropObject in Korrespondenz mit dem DropFrame:

Code:
import java.awt.datatransfer.*;
import java.awt.dnd.*;
import java.io.*;
import javax.swing.*;

public class DropObject extends DropTargetAdapter{
DropFrame dropFrame;
  public static final DataFlavor panelFlavor = new DataFlavor(MovePanel.class, "Move Panel");

  private static final DataFlavor[] flavors = new DataFlavor[] {
    panelFlavor
  };
//------------------------------------------------------------------------------------------------
  public DropObject(DropFrame d){
    dropFrame = d;
  }
//------------------------------------------------------------------------------------------------
  public void drop(DropTargetDropEvent dtde) {
    Transferable transferable = dtde.getTransferable();
    dtde.acceptDrop(DnDConstants.ACTION_COPY);

    if(dtde.isDataFlavorSupported(panelFlavor)){
      try {
        MovePanel movePanel = (MovePanel)transferable.getTransferData(panelFlavor);
        dropFrame.setPanel(movePanel);
      }
      catch (UnsupportedFlavorException e) {
        JOptionPane.showMessageDialog(null,e.getMessage(),"Information",JOptionPane.INFORMATION_MESSAGE);
      }
      catch (IOException e) {
        JOptionPane.showMessageDialog(null,e.getMessage(),"Information",JOptionPane.INFORMATION_MESSAGE);
      }
    }
  }
//------------------------------------------------------------------------------------------------
}

Nun meine Fragen:

1. Wie kann ich beim droppen die Mausposition im DropFrame feststellen?
2. Wie wird festgestellt, ob ich verschieben (STRG-Taste) oder kopieren (keine Metataste) will?
3. Wie bekommt dea DragFrame mitgeteilt, das es beim verschieben aktiv werden muss (Object löschen).

Bin über jede konstruktive Hilfe dankbar.

Grüss Max
 
Zu 1: In der DropObject#drop:
dropFrame.setPanel(movePanel, dtde.getLocation()); // Position aus mit an setPanel dtde übergeben
(unabhängig davon, ob diese Methode aufgerufen wird :wink: )

Zu 2:
Code:
  public void dropActionChanged(DragSourceDragEvent dsde)
  {
      System.out.println("Frage 2");
  }

Zu 3: Die MovePanels müßten dafür (im Moment) den DragFrame kennen. Aber von der Struktur her könnte man das vielleicht auch schöner machen.
 
http://www.java-forum.org/de/topic74262_drag-and-drop-fragen.html

Drag and Drop: 3 Fragen


Vielen Dank für die Antworten. Ich habe die Anregungen aufgenommen und eingebaut. Viola, es geht...
Hier, wen es interessiert, die geänderten Klassen:

Das Panel das per DnD verschoben werden soll:

Code:
import java.awt.*;
import java.awt.event.*;
import java.awt.datatransfer.*;
import java.awt.dnd.*;
import java.awt.image.*;
import javax.swing.*;
import javax.swing.border.*;

public class MovePanel extends JPanel implements DragGestureListener, DragSourceListener{
  JTextField textField = new JTextField();
  JLabel imageLabel = new JLabel();
  JCheckBox checkbox = new JCheckBox("Check Box" ,true);
  int id;
  String string;
  Color color;
  private DragSource dragSource;
  DragFrame dragFrame;

//------------------------------------------------------------------------------------------------
  public MovePanel(String s, Color c, int x, int y, int i, DragFrame d){
    string = s;
    color = c;
    id = i;
    dragFrame = d;
    setLayout(null);
    setLocation(x, y);
    setSize(180,160);
    setBackground(Color.WHITE);
    setBorder(new LineBorder(Color.black));

    imageLabel.setBounds(10,10,160,120);
    imageLabel.setIcon(new ImageIcon(createImage(string, color)));
    textField.setText(string);
    textField.setBounds(10,137,100,19);
    checkbox.setBounds(142,137,18,19);

    add(imageLabel);
    add(textField);
    add(checkbox);

    dragSource = new DragSource();
    dragSource.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_COPY_OR_MOVE, this);
  }
//------------------------------------------------------------------------------------------------
  public void setMovePanelLocation(Point p){
    setLocation(p);
  }

//------------------------------------------------------------------------------------------------
  public void setMovePanelLocation(int x,int y){
    setLocation(x,y);
  }
//------------------------------------------------------------------------------------------------
  public int getId(){
    return id;
  }
//------------------------------------------------------------------------------------------------
  public DragFrame getDragFrame(){
    return dragFrame;
  }
//------------------------------------------------------------------------------------------------
  public void dragGestureRecognized(DragGestureEvent dge){
    Transferable t = new PanelTransferable(this);
    dragSource.startDrag(dge, DragSource.DefaultMoveDrop, t, this);
  }
//------------------------------------------------------------------------------------------------
  public void dragEnter(DragSourceDragEvent dsde){}
//------------------------------------------------------------------------------------------------
  public void dragOver(DragSourceDragEvent dsde){}
//------------------------------------------------------------------------------------------------
  public void dropActionChanged(DragSourceDragEvent dsde){

    if(dsde.getGestureModifiers() == InputEvent.BUTTON1_MASK){
      dsde.getDragSourceContext().setCursor(DragSource.DefaultMoveDrop);
    }
    if(dsde.getGestureModifiers() == (InputEvent.BUTTON1_MASK | InputEvent.CTRL_MASK)){
      dsde.getDragSourceContext().setCursor(DragSource.DefaultCopyDrop);
    }
  }
//------------------------------------------------------------------------------------------------
  public void dragDropEnd(DragSourceDropEvent dsde) {}
//------------------------------------------------------------------------------------------------
  public void dragExit(DragSourceEvent dsde) {}
//------------------------------------------------------------------------------------------------
  public BufferedImage createImage(String s, Color c){
    BufferedImage bufferedImage = new BufferedImage(162, 120, BufferedImage.TYPE_3BYTE_BGR);
    Graphics g = bufferedImage.createGraphics();

    g.setColor(c);
    g.fillRect(0,0,160,120);
    g.setColor(Color.BLUE);
    g.drawString(s, 10,20);
    return bufferedImage;
  }
//------------------------------------------------------------------------------------------------
}


Das Quellframe zum draggen:
Code:
import java.awt.*;
import javax.swing.*;

public class DragFrame extends JFrame{
MovePanel myPanel01 = new MovePanel("Eins", Color.red,10,10,0,this);
MovePanel myPanel02 = new MovePanel("Zwei", Color.green,200,10,1,this);
//------------------------------------------------------------------------------------------------
  public DragFrame(){
    super("Drag Frame");
    setLayout(null);
    add(myPanel01);
    add(myPanel02);
  }
//------------------------------------------------------------------------------------------------
  public void rmPanel(int i){
    System.out.println("DragFrame#rmPanel(int i) " + i);
  }
//------------------------------------------------------------------------------------------------
  public static void main(String args[]){
  DragFrame app = new DragFrame();
    app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    app.setBounds(10,10,400,260);
    app.setVisible(true);
  }
//------------------------------------------------------------------------------------------------
}

Das Zielframe zum droppen:

Code:
import java.awt.dnd.*;
import javax.swing.*;

public class DropFrame extends JFrame{
  DropTarget target = new DropTarget(this, new DropObject(this));
//------------------------------------------------------------------------------------------------
  public DropFrame(){
    super("Drop Frame");
    this.setLayout(null);
    setDropTarget(target);
  }
//------------------------------------------------------------------------------------------------
  public void setPanel(MovePanel m, int i){
    MovePanel movePanel = m;

    if(i == DnDConstants.ACTION_MOVE){
      movePanel.getDragFrame().rmPanel(movePanel.getId());
    }

    add(movePanel);
    repaint();
  }
//------------------------------------------------------------------------------------------------
  public static void main(String args[]){
  DropFrame app = new DropFrame();
    app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    app.setBounds(420,10,400,260);
    app.setVisible(true);
  }
//------------------------------------------------------------------------------------------------
}

Und schliesslich ein DropObject in Korrespondenz mit dem DropFrame:

Code:
import java.awt.datatransfer.*;
import java.awt.dnd.*;
import java.io.*;
import javax.swing.*;

public class DropObject extends DropTargetAdapter{
DropFrame dropFrame;
  public static final DataFlavor panelFlavor = new DataFlavor(MovePanel.class, "Move Panel");

  private static final DataFlavor[] flavors = new DataFlavor[] {
    panelFlavor
  };
//------------------------------------------------------------------------------------------------
  public DropObject(DropFrame d){
    dropFrame = d;
  }
//------------------------------------------------------------------------------------------------
  public void drop(DropTargetDropEvent dtde) {
    Transferable transferable = dtde.getTransferable();
    dtde.acceptDrop(DnDConstants.ACTION_COPY);

    if(dtde.isDataFlavorSupported(panelFlavor)){
      try {
        MovePanel movePanel = (MovePanel)transferable.getTransferData(panelFlavor);
        dropFrame.setPanel(movePanel);
      }
      catch (UnsupportedFlavorException e) {
        JOptionPane.showMessageDialog(null,e.getMessage(),"Information",JOptionPane.INFORMATION_MESSAGE);
      }
      catch (IOException e) {
        JOptionPane.showMessageDialog(null,e.getMessage(),"Information",JOptionPane.INFORMATION_MESSAGE);
      }
    }
  }
//------------------------------------------------------------------------------------------------
}


@ Wildcard: Selbstverständlich habe ich dort nachgeschaut, aber bei dem API geht es mir manchmal wie bei Nietsches Versuch einer Selbstkritik, ich lese es aber verstehe es nicht.
Auf deine Anmerkung habe ich mich tiefer in die Klassen eingearbeitet und bin fündig geworden.

@ Marco13: Top Antworten, bei Antwort 2 habe ich etwas geknobelt, aber durch Wildcart's Antwort habe ich mich mit den Drag und Drop Events beschäftig.


Marco13 hat gesagt.:
Aber von der Struktur her könnte man das vielleicht auch schöner machen.

Stimme ich voll und ganz zu. Für dieses "bisschen" Drag 'n Drop so ein Aufwand. Wie könnte es besser gemacht werden?

Grüss und nochmals Danke

Max
 
Status
Nicht offen für weitere Antworten.

Neue Themen


Zurück
Oben