Swing Drag&Drop mit TransferHandler und JPanels

S

shadowdiver

Gast
Hallo,

ich stehe gerade vor einem Problem bei dem ich irgendwie keine richtige Lösung zu stande bekomme.

Panel1 ist innerhalb von Panel2 und soll per drag & drop in Panel3 verschoben werden.

Meine Recherche hat ergeben, dass dies mit dem TransferHandler gehen soll. Allerdings habe ich es nicht zum Laufen gebracht.
Etwas ähnliches habe ich hier im Forum gefunden:
http://www.java-forum.org/awt-swing-swt/103602-drag-drop-jpanel-jpanel-problem-dataflavor.html
Habe ich aber nicht genug verstanden um es bei mir anwenden zu können.

Wäre sehr froh darüber, wenn mir jemand ein funktionierendes Beispiel geben könnte.

Grüße
shadowdiver
 
S

shadowdiver

Gast
Nachdem ich noch immer keine Lösung für mein Problem habe und auch keiner geantwortet hat pushe ich diesen Post nochmal.
 

Melfis

Aktives Mitglied
Hier hast du einen Beispielcode(Ist nicht von mir).
Drag&Drop ist ein Umfangreiches Thema,
in manchen fällen kann ein Kontextmenü die benötigte Funktion ersetzten.

Java:
/*
 * Copyright (c) 2000 David Flanagan.  All rights reserved.
 * This code is from the book Java Examples in a Nutshell, 2nd Edition.
 * It is provided AS-IS, WITHOUT ANY WARRANTY either expressed or implied.
 * You may study, use, and modify it for any non-commercial purpose.
 * You may distribute it non-commercially as long as you retain this notice.
 * For a commercial use license, or to purchase the book (recommended),
 * visit [url]http://www.davidflanagan.com/javaexamples2[/url].
 */

import java.awt.BasicStroke;

/**
 * This component can operate in two modes. In "draw mode", it allows the user
 * to scribble with the mouse. In "drag mode", it allows the user to drag
 * scribbles with the mouse. Regardless of the mode, it always allows scribbles
 * to be dropped on it from other applications.
 */
public class ScribbleDragAndDrop extends JComponent implements
    DragGestureListener, // For recognizing the start of drags
    DragSourceListener, // For processing drag source events
    DropTargetListener, // For processing drop target events
    MouseListener, // For processing mouse clicks
    MouseMotionListener // For processing mouse drags
{
  ArrayList scribbles = new ArrayList(); // A list of Scribbles to draw

  Scribble currentScribble; // The scribble in progress

  Scribble beingDragged; // The scribble being dragged

  DragSource dragSource; // A central DnD object

  boolean dragMode; // Are we dragging or scribbling?

  // These are some constants we use
  static final int LINEWIDTH = 3;

  static final BasicStroke linestyle = new BasicStroke(LINEWIDTH);

  static final Border normalBorder = new BevelBorder(BevelBorder.LOWERED);

  static final Border dropBorder = new BevelBorder(BevelBorder.RAISED);

  /** The constructor: set up drag-and-drop stuff */
  public ScribbleDragAndDrop() {
    // Give ourselves a nice default border.
    // We'll change this border during drag-and-drop.
    setBorder(normalBorder);

    // Register listeners to handle drawing
    addMouseListener(this);
    addMouseMotionListener(this);

    // Create a DragSource and DragGestureRecognizer to listen for drags
    // The DragGestureRecognizer will notify the DragGestureListener
    // when the user tries to drag an object
    dragSource = DragSource.getDefaultDragSource();
    dragSource.createDefaultDragGestureRecognizer(this, // What component
        DnDConstants.ACTION_COPY_OR_MOVE, // What drag types?
        this);// the listener

    // Create and set up a DropTarget that will listen for drags and
    // drops over this component, and will notify the DropTargetListener
    DropTarget dropTarget = new DropTarget(this, // component to monitor
        this); // listener to notify
    this.setDropTarget(dropTarget); // Tell the component about it.
  }

  /**
   * The component draws itself by drawing each of the Scribble objects.
   */
  public void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2 = (Graphics2D) g;
    g2.setStroke(linestyle); // Specify wide lines

    int numScribbles = scribbles.size();
    for (int i = 0; i < numScribbles; i++) {
      Scribble s = (Scribble) scribbles.get(i);
      g2.draw(s); // Draw the scribble
    }
  }

  public void setDragMode(boolean dragMode) {
    this.dragMode = dragMode;
  }

  public boolean getDragMode() {
    return dragMode;
  }

  /**
   * This method, and the following four methods are from the MouseListener
   * interface. If we're in drawing mode, this method handles mouse down
   * events and starts a new scribble.
   */
  public void mousePressed(MouseEvent e) {
    if (dragMode)
      return;
    currentScribble = new Scribble();
    scribbles.add(currentScribble);
    currentScribble.moveto(e.getX(), e.getY());
  }

  public void mouseReleased(MouseEvent e) {
  }

  public void mouseClicked(MouseEvent e) {
  }

  public void mouseEntered(MouseEvent e) {
  }

  public void mouseExited(MouseEvent e) {
  }

  /**
   * This method and mouseMoved() below are from the MouseMotionListener
   * interface. If we're in drawing mode, this method adds a new point to the
   * current scribble and requests a redraw
   */
  public void mouseDragged(MouseEvent e) {
    if (dragMode)
      return;
    currentScribble.lineto(e.getX(), e.getY());
    repaint();
  }

  public void mouseMoved(MouseEvent e) {
  }

  /**
   * This method implements the DragGestureListener interface. It will be
   * invoked when the DragGestureRecognizer thinks that the user has initiated
   * a drag. If we're not in drawing mode, then this method will try to figure
   * out which Scribble object is being dragged, and will initiate a drag on
   * that object.
   */
  public void dragGestureRecognized(DragGestureEvent e) {
    // Don't drag if we're not in drag mode
    if (!dragMode)
      return;

    // Figure out where the drag started
    MouseEvent inputEvent = (MouseEvent) e.getTriggerEvent();
    int x = inputEvent.getX();
    int y = inputEvent.getY();

    // Figure out which scribble was clicked on, if any by creating a
    // small rectangle around the point and testing for intersection.
    Rectangle r = new Rectangle(x - LINEWIDTH, y - LINEWIDTH,
        LINEWIDTH * 2, LINEWIDTH * 2);
    int numScribbles = scribbles.size();
    for (int i = 0; i < numScribbles; i++) { // Loop through the scribbles
      Scribble s = (Scribble) scribbles.get(i);
      if (s.intersects(r)) {
        // The user started the drag on top of this scribble, so
        // start to drag it.

        // First, remember which scribble is being dragged, so we can
        // delete it later (if this is a move rather than a copy)
        beingDragged = s;

        // Next, create a copy that will be the one dragged
        Scribble dragScribble = (Scribble) s.clone();
        // Adjust the origin to the point the user clicked on.
        dragScribble.translate(-x, -y);

        // Choose a cursor based on the type of drag the user initiated
        Cursor cursor;
        switch (e.getDragAction()) {
        case DnDConstants.ACTION_COPY:
          cursor = DragSource.DefaultCopyDrop;
          break;
        case DnDConstants.ACTION_MOVE:
          cursor = DragSource.DefaultMoveDrop;
          break;
        default:
          return; // We only support move and copys
        }

        // Some systems allow us to drag an image along with the
        // cursor. If so, create an image of the scribble to drag
        if (dragSource.isDragImageSupported()) {
          Rectangle scribbleBox = dragScribble.getBounds();
          Image dragImage = this.createImage(scribbleBox.width,
              scribbleBox.height);
          Graphics2D g = (Graphics2D) dragImage.getGraphics();
          g.setColor(new Color(0, 0, 0, 0)); // transparent background
          g.fillRect(0, 0, scribbleBox.width, scribbleBox.height);
          g.setColor(Color.black);
          g.setStroke(linestyle);
          g.translate(-scribbleBox.x, -scribbleBox.y);
          g.draw(dragScribble);
          Point hotspot = new Point(-scribbleBox.x, -scribbleBox.y);

          // Now start dragging, using the image.
          e.startDrag(cursor, dragImage, hotspot, dragScribble, this);
        } else {
          // Or start the drag without an image
          e.startDrag(cursor, dragScribble, this);
        }
        // After we've started dragging one scribble, stop looking
        return;
      }
    }
  }

  /**
   * This method, and the four unused methods that follow it implement the
   * DragSourceListener interface. dragDropEnd() is invoked when the user
   * drops the scribble she was dragging. If the drop was successful, and if
   * the user did a "move" rather than a "copy", then we delete the dragged
   * scribble from the list of scribbles to draw.
   */
  public void dragDropEnd(DragSourceDropEvent e) {
    if (!e.getDropSuccess())
      return;
    int action = e.getDropAction();
    if (action == DnDConstants.ACTION_MOVE) {
      scribbles.remove(beingDragged);
      beingDragged = null;
      repaint();
    }
  }

  // These methods are also part of DragSourceListener.
  // They are invoked at interesting points during the drag, and can be
  // used to perform "drag over" effects, such as changing the drag cursor
  // or drag image.
  public void dragEnter(DragSourceDragEvent e) {
  }

  public void dragExit(DragSourceEvent e) {
  }

  public void dropActionChanged(DragSourceDragEvent e) {
  }

  public void dragOver(DragSourceDragEvent e) {
  }

  // The next five methods implement DropTargetListener

  /**
   * This method is invoked when the user first drags something over us. If we
   * understand the data type being dragged, then call acceptDrag() to tell
   * the system that we're receptive. Also, we change our border as a "drag
   * under" effect to signal that we can accept the drop.
   */
  public void dragEnter(DropTargetDragEvent e) {
    if (e.isDataFlavorSupported(Scribble.scribbleDataFlavor)
        || e.isDataFlavorSupported(DataFlavor.stringFlavor)) {
      e.acceptDrag(DnDConstants.ACTION_COPY_OR_MOVE);
      this.setBorder(dropBorder);
    }
  }

  /** The user is no longer dragging over us, so restore the border */
  public void dragExit(DropTargetEvent e) {
    this.setBorder(normalBorder);
  }

  /**
   * This is the key method of DropTargetListener. It is invoked when the user
   * drops something on us.
   */
  public void drop(DropTargetDropEvent e) {
    this.setBorder(normalBorder); // Restore the default border

    // First, check whether we understand the data that was dropped.
    // If we supports our data flavors, accept the drop, otherwise reject.
    if (e.isDataFlavorSupported(Scribble.scribbleDataFlavor)
        || e.isDataFlavorSupported(DataFlavor.stringFlavor)) {
      e.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
    } else {
      e.rejectDrop();
      return;
    }

    // We've accepted the drop, so now we attempt to get the dropped data
    // from the Transferable object.
    Transferable t = e.getTransferable(); // Holds the dropped data
    Scribble droppedScribble; // This will hold the Scribble object

    // First, try to get the data directly as a scribble object
    try {
      droppedScribble = (Scribble) t
          .getTransferData(Scribble.scribbleDataFlavor);
    } catch (Exception ex) { // unsupported flavor, IO exception, etc.
      // If that doesn't work, try to get it as a String and parse it
      try {
        String s = (String) t.getTransferData(DataFlavor.stringFlavor);
        droppedScribble = Scribble.parse(s);
      } catch (Exception ex2) {
        // If we still couldn't get the data, tell the system we failed
        e.dropComplete(false);
        return;
      }
    }

    // If we get here, we've got the Scribble object
    Point p = e.getLocation(); // Where did the drop happen?
    droppedScribble.translate(p.getX(), p.getY()); // Move it there
    scribbles.add(droppedScribble); // add to display list
    repaint(); // ask for redraw
    e.dropComplete(true); // signal success!
  }

  // These are unused DropTargetListener methods
  public void dragOver(DropTargetDragEvent e) {
  }

  public void dropActionChanged(DropTargetDragEvent e) {
  }

  /**
   * The main method. Creates a simple application using this class. Note the
   * buttons for switching between draw mode and drag mode.
   */
  public static void main(String[] args) {
    // Create a frame and put a scribble pane in it
    JFrame frame = new JFrame("ScribbleDragAndDrop");
    final ScribbleDragAndDrop scribblePane = new ScribbleDragAndDrop();
    frame.getContentPane().add(scribblePane, BorderLayout.CENTER);

    // Create two buttons for switching modes
    JToolBar toolbar = new JToolBar();
    ButtonGroup group = new ButtonGroup();
    JToggleButton draw = new JToggleButton("Draw");
    JToggleButton drag = new JToggleButton("Drag");
    draw.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        scribblePane.setDragMode(false);
      }
    });
    drag.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        scribblePane.setDragMode(true);
      }
    });
    group.add(draw);
    group.add(drag);
    toolbar.add(draw);
    toolbar.add(drag);
    frame.getContentPane().add(toolbar, BorderLayout.NORTH);

    // Start off in drawing mode
    draw.setSelected(true);
    scribblePane.setDragMode(false);

    // Pop up the window
    frame.setSize(400, 400);
    frame.setVisible(true);
  }
}

class Scribble implements Shape, Transferable, Serializable, Cloneable {
  protected double[] points = new double[64]; // The scribble data

  protected int numPoints = 0; // The current number of points

  double maxX = Double.NEGATIVE_INFINITY; // The bounding box

  double maxY = Double.NEGATIVE_INFINITY;

  double minX = Double.POSITIVE_INFINITY;

  double minY = Double.POSITIVE_INFINITY;

  /**
   * Begin a new polyline at (x,y). Note the use of Double.NaN in the points
   * array to mark the beginning of a new polyline
   */
  public void moveto(double x, double y) {
    if (numPoints + 3 > points.length)
      reallocate();
    // Mark this as the beginning of a new line
    points[numPoints++] = Double.NaN;
    // The rest of this method is just like lineto();
    lineto(x, y);
  }

  /**
   * Add the point (x,y) to the end of the current polyline
   */
  public void lineto(double x, double y) {
    if (numPoints + 2 > points.length)
      reallocate();
    points[numPoints++] = x;
    points[numPoints++] = y;

    // See if the point enlarges our bounding box
    if (x > maxX)
      maxX = x;
    if (x < minX)
      minX = x;
    if (y > maxY)
      maxY = y;
    if (y < minY)
      minY = y;
  }

  /**
   * Append the Scribble s to this Scribble
   */
  public void append(Scribble s) {
    int n = numPoints + s.numPoints;
    double[] newpoints = new double[n];
    System.arraycopy(points, 0, newpoints, 0, numPoints);
    System.arraycopy(s.points, 0, newpoints, numPoints, s.numPoints);
    points = newpoints;
    numPoints = n;
    minX = Math.min(minX, s.minX);
    maxX = Math.max(maxX, s.maxX);
    minY = Math.min(minY, s.minY);
    maxY = Math.max(maxY, s.maxY);
  }

  /**
   * Translate the coordinates of all points in the Scribble by x,y
   */
  public void translate(double x, double y) {
    for (int i = 0; i < numPoints; i++) {
      if (Double.isNaN(points[i]))
        continue;
      points[i++] += x;
      points[i] += y;
    }
    minX += x;
    maxX += x;
    minY += y;
    maxY += y;
  }

  /** An internal method to make more room in the data array */
  protected void reallocate() {
    double[] newpoints = new double[points.length * 2];
    System.arraycopy(points, 0, newpoints, 0, numPoints);
    points = newpoints;
  }

  /** Clone a Scribble object and its internal array of data */
  public Object clone() {
    try {
      Scribble s = (Scribble) super.clone(); // make a copy of all fields
      s.points = (double[]) points.clone(); // copy the entire array
      return s;
    } catch (CloneNotSupportedException e) { // This should never happen
      return this;
    }
  }

  /** Convert the scribble data to a textual format */
  public String toString() {
    StringBuffer b = new StringBuffer();
    for (int i = 0; i < numPoints; i++) {
      if (Double.isNaN(points[i])) {
        b.append("m ");
      } else {
        b.append(points[i]);
        b.append(' ');
      }
    }
    return b.toString();
  }

  /**
   * Create a new Scribble object and initialize it by parsing a string of
   * coordinate data in the format produced by toString()
   */
  public static Scribble parse(String s) throws NumberFormatException {
    StringTokenizer st = new StringTokenizer(s);
    Scribble scribble = new Scribble();
    while (st.hasMoreTokens()) {
      String t = st.nextToken();
      if (t.charAt(0) == 'm') {
        scribble.moveto(Double.parseDouble(st.nextToken()), Double
            .parseDouble(st.nextToken()));
      } else {
        scribble.lineto(Double.parseDouble(t), Double.parseDouble(st
            .nextToken()));
      }
    }
    return scribble;
  }

  // ========= The following methods implement the Shape interface ========

  /** Return the bounding box of the Shape */
  public Rectangle getBounds() {
    return new Rectangle((int) (minX - 0.5f), (int) (minY - 0.5f),
        (int) (maxX - minX + 0.5f), (int) (maxY - minY + 0.5f));
  }

  /** Return the bounding box of the Shape */
  public Rectangle2D getBounds2D() {
    return new Rectangle2D.Double(minX, minY, maxX - minX, maxY - minY);
  }

  /** Our shape is an open curve, so it never contains anything */
  public boolean contains(Point2D p) {
    return false;
  }

  public boolean contains(Rectangle2D r) {
    return false;
  }

  public boolean contains(double x, double y) {
    return false;
  }

  public boolean contains(double x, double y, double w, double h) {
    return false;
  }

  /**
   * Determine if the scribble intersects the specified rectangle by testing
   * each line segment individually
   */
  public boolean intersects(Rectangle2D r) {
    if (numPoints < 4)
      return false;
    int i = 0;
    double x1, y1, x2 = 0.0, y2 = 0.0;
    while (i < numPoints) {
      if (Double.isNaN(points[i])) { // If we're beginning a new line
        i++; // Skip the NaN
        x2 = points[i++];
        y2 = points[i++];
      } else {
        x1 = x2;
        y1 = y2;
        x2 = points[i++];
        y2 = points[i++];
        if (r.intersectsLine(x1, y1, x2, y2))
          return true;
      }
    }

    return false;
  }

  /** Test for intersection by invoking the method above */
  public boolean intersects(double x, double y, double w, double h) {
    return intersects(new Rectangle2D.Double(x, y, w, h));
  }

  /**
   * Return a PathIterator object that tells Java2D how to draw this scribble
   */
  public PathIterator getPathIterator(AffineTransform at) {
    return new ScribbleIterator(at);
  }

  /**
   * Return a PathIterator that doesn't include curves. Ours never does.
   */
  public PathIterator getPathIterator(AffineTransform at, double flatness) {
    return getPathIterator(at);
  }

  /**
   * This inner class implements the PathIterator interface to describe the
   * shape of a scribble. Since a Scribble is composed of arbitrary movetos
   * and linetos, we simply return their coordinates
   */
  public class ScribbleIterator implements PathIterator {
    protected int i = 0; // Position in array

    protected AffineTransform transform;

    public ScribbleIterator(AffineTransform transform) {
      this.transform = transform;
    }

    /** How to determine insideness and outsideness for this shape */
    public int getWindingRule() {
      return PathIterator.WIND_NON_ZERO;
    }

    /** Have we reached the end of the scribble path yet? */
    public boolean isDone() {
      return i >= numPoints;
    }

    /** Move on to the next segment of the path */
    public void next() {
      if (Double.isNaN(points[i]))
        i += 3;
      else
        i += 2;
    }

    /**
     * Get the coordinates of the current moveto or lineto as floats
     */
    public int currentSegment(float[] coords) {
      int retval;
      if (Double.isNaN(points[i])) { // If its a moveto
        coords[0] = (float) points[i + 1];
        coords[1] = (float) points[i + 2];
        retval = SEG_MOVETO;
      } else {
        coords[0] = (float) points[i];
        coords[1] = (float) points[i + 1];
        retval = SEG_LINETO;
      }

      // If a transform was specified, use it on the coordinates
      if (transform != null)
        transform.transform(coords, 0, coords, 0, 1);

      return retval;
    }

    /**
     * Get the coordinates of the current moveto or lineto as doubles
     */
    public int currentSegment(double[] coords) {
      int retval;
      if (Double.isNaN(points[i])) {
        coords[0] = points[i + 1];
        coords[1] = points[i + 2];
        retval = SEG_MOVETO;
      } else {
        coords[0] = points[i];
        coords[1] = points[i + 1];
        retval = SEG_LINETO;
      }
      if (transform != null)
        transform.transform(coords, 0, coords, 0, 1);
      return retval;
    }
  }

  //====== The following methods implement the Transferable interface =====

  // This is the custom DataFlavor for Scribble objects
  public static DataFlavor scribbleDataFlavor = new DataFlavor(
      Scribble.class, "Scribble");

  // This is a list of the flavors we know how to work with
  public static DataFlavor[] supportedFlavors = { scribbleDataFlavor,
      DataFlavor.stringFlavor };

  /** Return the data formats or "flavors" we know how to transfer */
  public DataFlavor[] getTransferDataFlavors() {
    return (DataFlavor[]) supportedFlavors.clone();
  }

  /** Check whether we support a given flavor */
  public boolean isDataFlavorSupported(DataFlavor flavor) {
    return (flavor.equals(scribbleDataFlavor) || flavor
        .equals(DataFlavor.stringFlavor));
  }

  /**
   * Return the scribble data in the requested format, or throw an exception
   * if we don't support the requested format
   */
  public Object getTransferData(DataFlavor flavor)
      throws UnsupportedFlavorException {
    if (flavor.equals(scribbleDataFlavor)) {
      return this;
    } else if (flavor.equals(DataFlavor.stringFlavor)) {
      return toString();
    } else
      throw new UnsupportedFlavorException(flavor);
  }
}
 
Zuletzt bearbeitet:
S

shadowdiver

Gast
Hat ein wenig gedauert, aber nun konnte ich mich wieder dieser Aufgabe zuwenden.

@Melfis: Dein Beispiel hat mir zum Verständis sehr geholfen, danke.

Mit dem neuen Wissen konnte ich das gepostete Beispiel zum Laufen bekommen.
Leider löst es nach wie vor nicht mein Problem von einem Panel zum Anderen zu verschieben.
Innerhalb des ersten Panels funktioniert es wunderbar.

Hier mal das was ich dran geändert habe:
Java:
public class NodePanel extends JPanel implements Transferable {
 
    private DataFlavor dataFlavor;
    
    public NodePanel() {
    	this.dataFlavor = DragAndDropTransferHandler.getNodePanelDataFlavor();
        //aussehen eines nodes
        this.setSize(150,150); //TODO die groesse setzen klappt nicht
DataFlavor wie angegeben in die Klasse "DragAndDropTransferHandler" verschoben. Hier den DataFlavor initialisiert.

Java:
public class DragAndDropTransferHandler extends TransferHandler {
	private static DataFlavor dataFlavor;
	
	static {
        try {
            //TODO
        	dataFlavor = new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType + ";class=NodePanel");
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    
    public static DataFlavor getNodePanelDataFlavor() {
    	System.out.println("getDF: "+dataFlavor);
        return dataFlavor;
    }
 
    public DragAndDropTransferHandler() {
        super();
    }
DataFlavor jetzt hier.

Java:
DataFlavor nodePanelDataFlavor = DragAndDropTransferHandler.getNodePanelDataFlavor();
Im TopologieLevel noch den DataFlavor umbiegen.

Java:
import javax.swing.SwingUtilities;
import java.awt.BorderLayout;
import javax.swing.JPanel;
import javax.swing.JFrame;
import java.awt.GridBagLayout;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.Color;

public class Test extends JFrame {

	private JPanel jContentPane = null;
	private JPanel westPanel = null;
	private JPanel eastPanel = null;
	private JPanel testPanel = null;

	/**
	 * This method initializes westPanel	
	 * 	
	 * @return javax.swing.JPanel	
	 */
	private JPanel getWestPanel() {
		if (westPanel == null) {
			GridBagConstraints gridBagConstraints = new GridBagConstraints();
			westPanel = new TopologyLevel();
			westPanel.setLayout(new GridBagLayout());
			westPanel.setPreferredSize(new Dimension(150, 0));
			westPanel.add(getTestPanel(), gridBagConstraints);
		}
		return westPanel;
	}

	/**
	 * This method initializes eastPanel	
	 * 	
	 * @return javax.swing.JPanel	
	 */
	private JPanel getEastPanel() {
		if (eastPanel == null) {
			eastPanel = new TopologyLevel();
			eastPanel.setLayout(new GridBagLayout());
			eastPanel.setPreferredSize(new Dimension(150, 0));
		}
		return eastPanel;
	}

	/**
	 * This method initializes testPanel	
	 * 	
	 * @return javax.swing.JPanel	
	 */
	private JPanel getTestPanel() {
		if (testPanel == null) {
			testPanel = new NodePanel();
			testPanel.setLayout(new GridBagLayout());
			testPanel.setPreferredSize(new Dimension(50, 50));
			testPanel.setBackground(new Color(238, 0, 0));
		}
		return testPanel;
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				Test thisClass = new Test();
				thisClass.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
				thisClass.setVisible(true);
			}
		});
	}

	/**
	 * This is the default constructor
	 */
	public Test() {
		super();
		initialize();
	}

	/**
	 * This method initializes this
	 * 
	 * @return void
	 */
	private void initialize() {
		this.setSize(316, 200);
		this.setContentPane(getJContentPane());
		this.setTitle("JFrame");
	}

	/**
	 * This method initializes jContentPane
	 * 
	 * @return javax.swing.JPanel
	 */
	private JPanel getJContentPane() {
		if (jContentPane == null) {
			jContentPane = new JPanel();
			jContentPane.setLayout(new BorderLayout());
			jContentPane.setPreferredSize(new Dimension(150, 0));
			jContentPane.add(getWestPanel(), BorderLayout.WEST);
			jContentPane.add(getEastPanel(), BorderLayout.EAST);
		}
		return jContentPane;
	}

}
Und die Testklasse mit allen nötigen Panels.

Villeicht versteht ihr mein Problem, wenn ihr das testet.
 

Marco13

Top Contributor
Poste in solchen Fällen ein KSKB. Wenn ich nicht zufällig gerade in einem anderen Thread was mit DnD gemacht hätte, hätte ich sicher nicht sowas hier zusammengestümpert
Java:
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragSource;
import java.awt.dnd.DragSourceDragEvent;
import java.awt.dnd.DragSourceDropEvent;
import java.awt.dnd.DragSourceEvent;
import java.awt.dnd.DragSourceListener;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.io.IOException;

import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;


public class ComponentDragDrop
{
    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {
                createAndShowGUI();
            }
        });
    }

    private static void createAndShowGUI()
    {
        JFrame f = new JFrame("Test");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        JPanel sourcePanel = new JPanel();
        sourcePanel.setBorder(BorderFactory.createTitledBorder("Source"));
        DragSource dragSource = DragSource.getDefaultDragSource();
        dragSource.createDefaultDragGestureRecognizer(sourcePanel,
            DnDConstants.ACTION_COPY_OR_MOVE, new ComponentDragger(sourcePanel));
        
        
        JPanel p0 = new JPanel();
        p0.setPreferredSize(new Dimension(50,50));
        p0.setBackground(Color.RED);
        sourcePanel.add(p0);

        JPanel p1 = new JPanel();
        p1.setPreferredSize(new Dimension(50,50));
        p1.setBackground(Color.GREEN);
        sourcePanel.add(p1);
        
        JPanel p2 = new JPanel();
        p2.setPreferredSize(new Dimension(50,50));
        p2.setBackground(Color.BLUE);
        sourcePanel.add(p2);
       
        
        JPanel targetPanel = new JPanel(null);
        targetPanel.setBorder(BorderFactory.createTitledBorder("Target"));
        @SuppressWarnings("unused")
        DropTarget dropTarget = 
            new DropTarget(targetPanel, 
                new ComponentDropTargetListener(targetPanel));

        JPanel panel = new JPanel(new GridLayout(0,2));
        panel.add(sourcePanel);
        panel.add(targetPanel);
        f.getContentPane().add(panel);
        f.setSize(800,400);
        f.setVisible(true);

    }


    static class ComponentDropTargetListener implements DropTargetListener
    {
        private static final long serialVersionUID = -5679944858109178081L;
        
        private JPanel targetPanel;
        
        public ComponentDropTargetListener(JPanel targetPanel)
        {
            this.targetPanel = targetPanel;
        }

        private void dropComponent(Component component, Point location)
        {
            System.out.println("Dropped at "+location+": "+component);
            targetPanel.add(component);
            component.setLocation(location);
            targetPanel.validate();
            targetPanel.repaint();
        }

        @Override
        public void drop(DropTargetDropEvent e)
        {
            Transferable transferable = e.getTransferable();
            
            if (transferable.isDataFlavorSupported(
                TransferableComponent.COMPONENT_FLAVOR))
            {
                try
                {
                    e.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
                    Component component = (Component)transferable.getTransferData(
                        TransferableComponent.COMPONENT_FLAVOR);
                    dropComponent(component, e.getLocation());
                }
                catch (UnsupportedFlavorException ex)
                {
                    e.rejectDrop();
                }
                catch (IOException ex)
                {
                    e.rejectDrop();
                }
            }
            else
            {
                e.rejectDrop();
            }
            e.getDropTargetContext().dropComplete(true);
        }


        @Override
        public void dragEnter(DropTargetDragEvent e)
        {
        }

        @Override
        public void dragOver(DropTargetDragEvent e)
        {
        }

        @Override
        public void dropActionChanged(DropTargetDragEvent e)
        {
        }

        @Override
        public void dragExit(DropTargetEvent e)
        {
        }
    }


    private static class TransferableComponent implements Transferable
    {
        private static final DataFlavor COMPONENT_FLAVOR = 
            new DataFlavor(Component.class, "Component");
        private final Component component;

        TransferableComponent(Component component)
        {
            this.component = component;
        }

        @Override
        public DataFlavor[] getTransferDataFlavors()
        {
            return new DataFlavor[]{ COMPONENT_FLAVOR };
        }

        @Override
        public boolean isDataFlavorSupported(DataFlavor flavor)
        {
            return COMPONENT_FLAVOR.equals(flavor);
        }

        @Override
        public Object getTransferData(DataFlavor flavor) 
        throws UnsupportedFlavorException
        {
            if (isDataFlavorSupported(flavor))
            {
                return component;
            }
            throw new UnsupportedFlavorException(flavor);
        }

    }

    private static class ComponentDragger implements DragGestureListener, DragSourceListener
    {
        private JComponent sourceComponent;
        private Component dragged = null; 
        
        ComponentDragger(JComponent sourceComponent)
        {
            this.sourceComponent = sourceComponent;
        }

        @Override
        public void dragGestureRecognized(DragGestureEvent e) 
        {
            Point p = e.getDragOrigin();
            dragged = 
                SwingUtilities.getDeepestComponentAt(sourceComponent, p.x, p.y);
            Transferable transferable = new TransferableComponent(dragged);
            e.startDrag(null, transferable, this);
        }

        @Override
        public void dragDropEnd(DragSourceDropEvent e)
        {
            if (dragged != null)
            {
                if (e.getDropSuccess())
                {
                    sourceComponent.remove(dragged);
                    sourceComponent.validate();
                    sourceComponent.repaint();
                }
            }
        }
        
        @Override
        public void dragEnter(DragSourceDragEvent e) 
        {
        }

        @Override
        public void dragOver(DragSourceDragEvent e)
        {
        }

        @Override
        public void dragExit(DragSourceEvent e)
        {
        }

        @Override
        public void dropActionChanged(DragSourceDragEvent e)
        {
        }


    }
    
}

Und bevor du sagst: Oh, das geht nur in eine Richtung, und nicht mit JButtons, und und und...: Ja. Wenn du ein Docking-Framework brauchst, hilft dir so ein DnD-Beispiel nicht.
 
S

shadowdiver

Gast
Danke Marco, dein Beispiel kommt schon sehr nahe an das heran was ich brauche.
Nur brauche ich genau das von dir angesprochene in beide Richtungen verschieben.
Es geht konkret darum Belegungen von einem Raum zum Anderen verschieben zu können (und auch wieder zurück) und nicht nur zu einer anderen Zeit innerhalb eines Raums.
Gibt es dafür noch eine brauchbare Lösung oder ist es wirklich besser es bei dem bereits vorhandenen Kontextmenü zu belassen?

Das mit dem KSKB hatte ich erst überlegt, aber ich wollte nicht den Code aus dem anderen Post fast 1:1 hier nochmal posten.
 

Marco13

Top Contributor
Hast du schon versucht, es selbst auf beide Richtungen zu erweitern? Wenn's nicht klappt, schau ich vielleicht nochmal, aber... muss mal sehen, ob/wann ich Zeit habe...
 
S

shadowdiver

Gast
Ich hatte jetzt leider auch nicht viel Zeit mir Gedanken drüber zu machen.

Aber gerade als ich diese Antwort Posten wollte ist mir aufgefallen was ich bei meinem ersten Versuch das umzubauen falsch gemacht hatte. Jetzt geht es.

Nochmals vielen Dank für dein Beispiel und die Hilfe.

Hier der Codeteil dazu:
Java:
JPanel sourcePanel = new JPanel();
        sourcePanel.setBorder(BorderFactory.createTitledBorder("Source"));
        DragSource dragSource = DragSource.getDefaultDragSource();
        dragSource.createDefaultDragGestureRecognizer(sourcePanel,
            DnDConstants.ACTION_COPY_OR_MOVE, new ComponentDragger(sourcePanel));
        sourcePanel.setBorder(BorderFactory.createTitledBorder("Target"));
        @SuppressWarnings("unused")
        DropTarget dropTarget = 
            new DropTarget(sourcePanel, 
                new ComponentDropTargetListener(sourcePanel));
        
        
        JPanel p0 = new JPanel();
        p0.setPreferredSize(new Dimension(50,50));
        p0.setBackground(Color.RED);
        sourcePanel.add(p0);
 
        JPanel p1 = new JPanel();
        p1.setPreferredSize(new Dimension(50,50));
        p1.setBackground(Color.GREEN);
        sourcePanel.add(p1);
        
        JPanel p2 = new JPanel();
        p2.setPreferredSize(new Dimension(50,50));
        p2.setBackground(Color.BLUE);
        sourcePanel.add(p2);
       
        
        JPanel targetPanel = new JPanel(null);
        targetPanel.setBorder(BorderFactory.createTitledBorder("Target"));
        DragSource dragSource2 = DragSource.getDefaultDragSource();
        dragSource2.createDefaultDragGestureRecognizer(targetPanel,
                DnDConstants.ACTION_COPY_OR_MOVE, new ComponentDragger(targetPanel));
            sourcePanel.setBorder(BorderFactory.createTitledBorder("Target"));
        @SuppressWarnings("unused")
        DropTarget dropTarget2 = 
            new DropTarget(targetPanel, 
                new ComponentDropTargetListener(targetPanel));
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
A TransferHandler & Drag n' Drop AWT, Swing, JavaFX & SWT 2
MasterEvil Drag n Drop -Transferhandler . get Drop Location ? AWT, Swing, JavaFX & SWT 2
H MouseEvent bei Drag & Drop (mittels TransferHandler) AWT, Swing, JavaFX & SWT 3
J Drag und drop aus einer JTable - bitte um Unterstützung AWT, Swing, JavaFX & SWT 2
G JPanel per Drag and Drop JButtons und Bilder ablegen AWT, Swing, JavaFX & SWT 1
AmsananKING ListView Drag And Drop AWT, Swing, JavaFX & SWT 0
AmsananKING Drag And Drop Filenames Inside A Listview AWT, Swing, JavaFX & SWT 1
DonBronson Java Graphics bewegbar machen (Drag&Drop) AWT, Swing, JavaFX & SWT 3
M Polygon per Drag&Drop verschieben AWT, Swing, JavaFX & SWT 26
Z Swing Drag and Drop mit einem JButton AWT, Swing, JavaFX & SWT 1
N Drag and Drop Fenster AWT, Swing, JavaFX & SWT 11
F Drag&Drop mit Transparenter Farbe bei PNG AWT, Swing, JavaFX & SWT 0
D JavaFX Pane per Drag&Drop bewegen? AWT, Swing, JavaFX & SWT 2
L JavaFX Drag and Drop funktioniert nicht AWT, Swing, JavaFX & SWT 3
J Drag and Drop von eigenen Objekten AWT, Swing, JavaFX & SWT 3
J Drag and Drop eines Buttons AWT, Swing, JavaFX & SWT 0
T Swing Drag and Drop für JComponents AWT, Swing, JavaFX & SWT 1
Z Swing Drag&Drop zwischen JTable und JTree AWT, Swing, JavaFX & SWT 4
F Drag und Drop AWT, Swing, JavaFX & SWT 0
L JavaFX JavaFX Chart Drag and Drop AWT, Swing, JavaFX & SWT 3
D JavaFX Drag&Drop mehrerer TreeViews oder TableViews AWT, Swing, JavaFX & SWT 1
P Drag & Drop zwischen Panels AWT, Swing, JavaFX & SWT 0
U Drag and Drop mit imageview AWT, Swing, JavaFX & SWT 0
U Drag and Drop imageviews AWT, Swing, JavaFX & SWT 8
D SteelSeries in Netbeans als Drag-and-Drop einbinden AWT, Swing, JavaFX & SWT 0
C JTable Drag and Drop von Zeilen innerhalb einer Table AWT, Swing, JavaFX & SWT 2
S Swing Update eine JTabelle nach einer Drag&Drop Operation AWT, Swing, JavaFX & SWT 0
S Swing Suche Drag & Drop Beispiele AWT, Swing, JavaFX & SWT 1
A Drag and Drop mit JAVAFX- Scenebuilder AWT, Swing, JavaFX & SWT 1
R Performance Drag and Drop & Timer AWT, Swing, JavaFX & SWT 3
R Drag and Drop Problem auf Jpanel AWT, Swing, JavaFX & SWT 2
N Swing JTable und Drag und Drop AWT, Swing, JavaFX & SWT 2
A Drag and Drop eigener Objekte AWT, Swing, JavaFX & SWT 7
C Drag and Drop (inventar) AWT, Swing, JavaFX & SWT 15
F Swing Drag and Drop in JTree aus verschiedenen Listen AWT, Swing, JavaFX & SWT 6
T Swing JButton per Drag&Drop verschieben AWT, Swing, JavaFX & SWT 5
Iron Monkey JFileChooser - Drag and Drop AWT, Swing, JavaFX & SWT 5
Iron Monkey Nach Drag & Drop die Datei auf Komponent darstellen AWT, Swing, JavaFX & SWT 2
M AWT Drag n Drop-Support für Component AWT, Swing, JavaFX & SWT 5
HaukeG Swing Drag & Drop in verschiedenen Varianten AWT, Swing, JavaFX & SWT 4
C Swing Simulation von Drag and Drop Events AWT, Swing, JavaFX & SWT 3
H Swing "Drag and Drop" eines JComponent über ein JPanel AWT, Swing, JavaFX & SWT 2
R Drag 'n Drop AWT, Swing, JavaFX & SWT 3
S Selektion bei Drag&Drop AWT, Swing, JavaFX & SWT 4
C Swing Drag and Drop mit Objekten in einem Fenster. AWT, Swing, JavaFX & SWT 9
T SWT Drag&Drop: Eclipse FileTransfer mit Icons AWT, Swing, JavaFX & SWT 14
F Drag & Drop durch Verbindungslinien AWT, Swing, JavaFX & SWT 10
T Swing Drag and Drop - JLabels tauschen statt überschreiben AWT, Swing, JavaFX & SWT 11
S Drag and Drop über 2 Panels AWT, Swing, JavaFX & SWT 2
K JButtons innerhalb eines JPanels verschieben (DRAG&DROP) AWT, Swing, JavaFX & SWT 5
B Drag and Drop AWT, Swing, JavaFX & SWT 6
K Drag and Drop Workbench AWT, Swing, JavaFX & SWT 2
P SWT Eclipse Draw2D Drag and Drop (ruckelt) AWT, Swing, JavaFX & SWT 4
F SWT Drag and Drop im TreeViewer AWT, Swing, JavaFX & SWT 4
B Swing Drag&Drop mit Feedback (Image am Mauszeiger) AWT, Swing, JavaFX & SWT 7
Spin JFrame/ Frame Drag and Drop AWT, Swing, JavaFX & SWT 13
R Drag an Drop JTable Zelle AWT, Swing, JavaFX & SWT 6
D Drag & Drop - node.isRoot AWT, Swing, JavaFX & SWT 3
E Swing Drag n Drop Verschieben von Labels o.ä. AWT, Swing, JavaFX & SWT 10
E Swing Beim Drag & Drop, Drag verbieten?! AWT, Swing, JavaFX & SWT 2
E JTree Autoscroll bei Drag and Drop AWT, Swing, JavaFX & SWT 4
F Swing Problem mit Drag&Drop in JTable AWT, Swing, JavaFX & SWT 4
C keine weiteren Events während Drag&Drop Operation möglich? AWT, Swing, JavaFX & SWT 5
E Drag&Drop zwischen 2 Listen AWT, Swing, JavaFX & SWT 5
0 Swing Drag n' Drop Bug wenn Source und Target gleiche Komponente? AWT, Swing, JavaFX & SWT 4
C Drag and Drop JPanel auf JPanel nach drop erneut verschieben? AWT, Swing, JavaFX & SWT 3
M Swing JTable Drag'n'Drop von Dateien AWT, Swing, JavaFX & SWT 3
M Drag and Drop: Quellfenster AWT, Swing, JavaFX & SWT 2
M Buttons per Drag & Drop im GridBagLayout verschieben AWT, Swing, JavaFX & SWT 6
M Swing JList > Drag & Drop AWT, Swing, JavaFX & SWT 2
C Drag an Drop vom JTree zur JTable AWT, Swing, JavaFX & SWT 4
Z Drag and Drop auf Application AWT, Swing, JavaFX & SWT 3
G Drag and Drop JTree to Canvas AWT, Swing, JavaFX & SWT 7
H Drag&Drop von JComponents AWT, Swing, JavaFX & SWT 6
G JTable drag and drop AWT, Swing, JavaFX & SWT 4
H Drag&Drop mit GWT AWT, Swing, JavaFX & SWT 8
B Swing Drag&Drop einzelner Zellen in einer JTable AWT, Swing, JavaFX & SWT 12
A Swing Drag and Drop TreeNode User Object AWT, Swing, JavaFX & SWT 3
P JList: Reihenfolge der Elemente per Drag'n'Drop ändern. AWT, Swing, JavaFX & SWT 9
K Swing Wie ändere ich die default action für Drag&Drop AWT, Swing, JavaFX & SWT 6
R JLayeredPane - Drag&Drop - mouseDragged AWT, Swing, JavaFX & SWT 6
C JTable mit RowSorter und Drag & Drop: Zeile verschieben AWT, Swing, JavaFX & SWT 4
V SWT TreeViewer Drag'n'Drop LocalSelectionTransfer AWT, Swing, JavaFX & SWT 10
R Swing JLayeredPane - Drag&Drop Positionen vertauschen AWT, Swing, JavaFX & SWT 3
F Drag & Drop mit eigenen Komponenten AWT, Swing, JavaFX & SWT 2
B SWT - Drag & Drop innerhalb einer Table AWT, Swing, JavaFX & SWT 3
S Drag'n'Drop AWT, Swing, JavaFX & SWT 8
E Drag&Drop JTable; Renderer füllt alle Zellen AWT, Swing, JavaFX & SWT 10
M Drag & Drop in Swing (createTransferable) AWT, Swing, JavaFX & SWT 6
T Drag Quelle beim Drop AWT, Swing, JavaFX & SWT 6
A Drag & Drop von Zeilen innerhalb einer Tabelle AWT, Swing, JavaFX & SWT 2
E Drag & Drop von jTree in JList AWT, Swing, JavaFX & SWT 5
P Dateien per Drag&Drop ins Java-Fenster ziehen AWT, Swing, JavaFX & SWT 8
G JTree Node ggf. aufklappen bei Drag & Drop? AWT, Swing, JavaFX & SWT 7
J Drag'n Drop imm selben Frame unterbinden AWT, Swing, JavaFX & SWT 3
S Table Row per Drag and Drop in andere Table schieben? AWT, Swing, JavaFX & SWT 14
X wiedermal Drag n Drop AWT, Swing, JavaFX & SWT 2
P Drag & Drop AWT, Swing, JavaFX & SWT 2
X Drag and Drop AWT, Swing, JavaFX & SWT 2
F Drag&Drop Jlist -> JList AWT, Swing, JavaFX & SWT 3

Ähnliche Java Themen

Neue Themen


Oben