# JFrame/ Frame Drag and Drop



## Spin (14. Apr 2011)

Hallo liebe Leute,

ich habe folgende einfache Klasse, die Klassen aufruft für Drag and Drop funktionalität.


```
public class DragAndDropPanelsDemo extends Frame
{
 JLabel button = new JLabel("Hello");
 JPanel panel = new JPanel();
 ComponentA component1=new ComponentA(button);

 public DragAndDropPanelsDemo()
 {
  addWindowListener(new WindowAdapter()
  {
   public void windowClosing(WindowEvent e)
   {
    dispose();
    System.exit(0);
   }
  });
  this.add(panel);
 // panel.add(component1);
  panel.add(button);
  
  new CanvasDragSource(button);
  new CanvasDropTarget(panel,button);
 }
 public static void main(String args[]) {
  System.out.println("Starting Drag And Drop Example ...");
  DragAndDropPanelsDemo mainFrame = new DragAndDropPanelsDemo();
  mainFrame.setSize(400, 400);
  mainFrame.setLocation(100,100);
  mainFrame.setTitle("Drag And Drop Example");
  mainFrame.setVisible(true);
 
  
 }
```

Ich leite von Frame ab und es funktioniert. ich kann das Label von oben rechts nach unten links verschieben.

Wehe ich leite von JFrame ab, dann gehts nicht mehr.

Ich habe dass panel schon vergrößerrt und dem ContentPane hinzugefügt, aber trotzdem geht es nicht.??

weiss einer einen rat? Ich denke es liegt daran wie ich das Panel dem Frame hinzugefügt habe. 

Danke , grüße Spin


----------



## Volvagia (14. Apr 2011)

Ich denke, es liegt eher daran, dass du keinen LayoutManager gesetzt hast -> JLayeredPane.


----------



## SlaterB (14. Apr 2011)

mit 500 Postings bitte keine JFrame Drag und Drop-Themen mehr mit schlimmen 'ärgert mich'-Titel im Java-Basics-Bereich posten,
es gibt auch andere Bereiche und bessere Titel


----------



## Spin (14. Apr 2011)

Hey Slater 

Du hast vollkommen recht - mein Überschrift war ein wenig daneben  Wollt nur ein wenig Aufmerksamkeit.


Das mit JLayeredPane ist ja eine nette Geschichte.

Ich habe vor mit drag and drop 5 Elemente neben einander zu schieben und sie müssen in der richtigen reihenfolge sein.

Dabei darf man sie nicht überlappen, beim ablegen.

Hat der User die richtige reihenfolge, soll ein roter rahmen um die 5 Elemente sein.

Meint ihr ich kann das auf dem JLayeredPane alles realisieren.
Habt ihr dazu paar Sachen die ich mir anschauen sollte?

vielen dank


----------



## Volvagia (14. Apr 2011)

Klar, ist für solche Sachen da.
Die Überschneidungen könntest du (wohl wieder nicht schön, aber ich bin nun mal nicht schön) mit Rectangle#intersects überprüfen.


----------



## Spin (14. Apr 2011)

Danke,

mein Idee ist es ein Gitter aufzuspannen welches auf einem JPanel liegt.
Jedes Raster darf ein JLabel empfangen, bzw es liegt in jedem Raster schon ein Jlabel oder es ist null.

Dann möchte ich gerne dass man dieses dort hinschiebt wo noch platz ist und ich schaue mir das mal mit interects an. Ich habe da schonmal was mit gemacht, als ein Ball von einer Wand abprallen sollte.

Ok die Idee ist da jetzt noch die Umsetzung ohje 

Derzeit geht das draggen und droppen, doch es finden noch keine Überprüfungen statt. Danke für die Hinweise , ich lasse den Thread noch auf und poste hier weiter , wenn ich nicht weiterkommen sollte.

grüße Spin:toll:


----------



## Spin (15. Apr 2011)

Hallo,

ich habe ja versprochen dass ich mich hier melde 

Ich habe nun alles hinbekommen. das verschieben , sowie die kollisionskontrolle.

Nun möchte ich gerne dass ein Layer nicht unter dem anderen verschwindet, bzw. ich möchte auf die Kollision Detection reagieren.


```
if(rectangle != null){
		   if(DragAndDropPanelsDemo.checkCollision(rectangle)){
			   setLocation (1,1);
	  	 	}
	   }
```

Dioe checkKollision liegt außerhalb von meine Klasse, die die Funktion verschieben hat. Das ist noch ziemlich doof von OOP her , aber dass baue ich alles um, wenn alles klappt ^^.


Ich reagiere hier auf eine Kollision, indem ich die neue Location des Labels auf 1,1 setze.

Das ist natürlich keine Lösung, deshalb der Forumbeitrag. Ich möchte das man nicht über ein Bild rüber schieben kann, sondern schon vorher geblockt wird. So wie ein Ball wieder von der Mauer zurückspringt. 

Dass realisiert mit dem Verschieben der Maus. Was brauche ich dazu? Wie kann ich java beibringen dass die bIlder nicht aufeinander liegen dürfen. Danke 

Logische Tipps sollten reichen


btw: java - Collision problems with drag-n-drop puzzle game. - Stack Overflow


----------



## Volvagia (15. Apr 2011)

Speichere doch die Letzte Position des Componenten, und wenn du eine Kollision endeckst setzt du ihm zurück?


----------



## Spin (15. Apr 2011)

Das löst mein Problem leider nicht.

Ich baue jetzt aber alles um , denn ich habe immer JComponeten verschieben wollen und dass geht mit JLAyeredPane oder über viele Schnittstellen , Package dnd

Aber so krass muss es nicht sein , ich nimm jetzt einfach paint() und gut ist und repainte beim verschieben das neue bild.

Trotzdem bleibt die Kollisionsfrage. Also was mache ich ???:L.

Ich muss oben, rechts , unten und links auf kollsion prüfen und wenn sie da ist , das aktuelle Objekt(welches Geschoben wird) um den Anteil zurückversetzen das es überliegt.

also :

Wenn das Objekt rechts drüber über ein andere liegt, bei dem qusi links:

Rechne ich aktuelle kannte von meinem objekt - die die linke kante von dem objekt welches überlappt wurde. Dann habe ich eine Deifferenz und kann diese von meiner rechten Kante abziehen. Dass denn überall und das müsste gehen ?

ich versuche es mal :rtfm:


----------



## Spin (16. Apr 2011)

Ok es funktioniert jetzt soweit alles, aber ich habe probleme mit dem Layoutmanager.

Wenn ich zwei objeke hinzufüge und dann komme ich immer aus meinen vorgesehenden Bereich raus. Egal welches Layout ich verwende.

Welches sollte man am besten nehmen bei drag and drop?
Einen eigenen schreiben?

Gibt es schon welche?

Danke für hinweise.
Java macht einen das Leben echt schwer.

ich dragge jetzt mit mousedragged.

Habe jetzt kein droptargetlistener oder so benutzt. Das ist jetzt bischen viel , aber komme ich villeicht nicht drum herum?

danke für info

gruß spin


----------



## Spin (16. Apr 2011)

Hallo , ich habe noch weiter gemacht aber ich habe komischen Sachen herausbekommen die ich nicht ansatzweise verstehe.


ich habe jetzt 3 JLabels die ich verschieben kann. Um diese JLabels wollte ich ein Rechteck legen, um später die Kollisionskontrolle durchzuführen.

Immer wenn ich das JLabel beweg, dann ist das Rechteck irgendwo aber nicht um das JLabel. Warum?

Beim Bewegen MouseMove:


```
this.setLocation (
					getX () + (e.getX () - offsetPoint.x),
					getY () + (e.getY () - offsetPoint.y));
			
			this.setBounds((int)this.getLocation().getX(), (int)this.getLocation().getY(), this.imageWidth, this.imageHeight);
```

Mit getX() und getY() hole ich mir die Koordinaten des JLabels und mit offsetPoint die koordinaten des mauszeigers im bezug auf das JLabel ( nicht des Frames)

Ich benutze ein NULL Layout, was echt zum heulen ist. Denn setBounds verstehe ich nicht.

Ich positioniere ein JLabel asl default an 100,100,imageWidth,imageHeight.

Wenn ich es verschiebe soll das setBounds geupdated werden, aber das geht nicht. Mit Location setze ich eine neue Position, aber das setBounds macht was es will.

Ich habe noch :



```
rectangle = new Rectangle(
						this.getLocation().x, 
						this.getLocation().y,this.imageWidth, this.imageHeight);
```


```
public void paintComponent(Graphics g) {
		super.paintComponent(g);
		Graphics2D g2 = (Graphics2D) g;
		// zeichnen
//		g2.drawString("x-Kooridnate: " + this.rectangle.x,10,10);
//		g2.drawString("y-Kooridnate: " + this.rectangle.y,10,25);
		g2.drawRect(this.rectangle.x,this.rectangle.y, this.rectangle.width, this.rectangle.height);
}
```

ich dachte wenn ich die Location beim bewegen immer neu setze kann ich daraufhin das neue Rechteck instanziieren und auch gleich zeichnen. 

Es wird irgendwo gezeichnet aber nicht um das JLabel.;(

Bin euch sehr dankbar über hilfe.

danka danke

grüße Spin


----------



## Volvagia (17. Apr 2011)

Wenn sich die Größe nicht ändert, und setLocation sowieso sehr viel sinnvoller.
Ständig ein Rectangle zu erzeugen ist sicher keine gute Idee. Die Variablen sind public. Alternativ könntest du noch getBounds verwenden, wobei ich nicht weiß, ob das nicht auch immer ein neues instanziert.
Etwas mehr Code oder ein KSKB wäre echt nützlich.


----------



## Spin (17. Apr 2011)

Denn hier mal der ganze code 


```
public class DragableTile extends Tile {

	// layer 
	public int originalLayer;
	
	// point fo Jlabel (x|y)
	public Point offsetPoint = null;
	
	// rectangle to chck collision
	public Rectangle rectangle = null;
	
	public int imageWidth =  0;
	public int imageHeight = 0;
	
	// test Vars
	public static int startPoint = 0;
	
	// list of all available Dragable Tiles
	public static ArrayList<DragableTile> dragableTileList = new ArrayList<DragableTile>();

	public enum TouchLocation {
		RIGHT, LEFT, TOP, BOTTOM, NONE;
	}

	public DragableTile(int tileNumber,int tileValue, int tileColor){
		super(tileNumber,tileValue,tileColor);
		
		this.imageWidth 	= this.getImage().getIconWidth();
		this.imageHeight	= this.getImage().getIconHeight();
		
		// every new component shoul'd get a new location
		DragableTile.startPoint += 100;
		
		// size and rectangle
		setBounds(0,0, 400,400);
		setLocation(0,0);
		rectangle = new Rectangle(this.getX(), this.getY(), this.imageWidth, this.imageHeight);
		setPreferredSize(new Dimension(this.imageWidth, this.imageHeight));
	
		// activate events (different way e.g. this.addMouseListener(this))
		enableEvents(MouseEvent.MOUSE_EVENT_MASK |
					 MouseEvent.MOUSE_MOTION_EVENT_MASK);
	}
	
	/**
	 * Mouse Motion
	 */
	protected void processMouseMotionEvent(MouseEvent e){
		
		// check offset != null - tile is moving
		if(this.offsetPoint != null){
			
			rectangle = new Rectangle(
					this.getLocation().x, 
					this.getLocation().y,this.imageWidth, this.imageHeight);
			System.out.println(rectangle);
			
			// default 100,100
			this.setLocation (
					getX () + (e.getX () - offsetPoint.x),
					getY () + (e.getY () - offsetPoint.y));
			
			//this.setBounds((int)this.getLocation().getX(), (int)this.getLocation().getY(), this.imageWidth, this.imageHeight);
			
			revalidate();
			System.out.println("X- K : " + getX () + (e.getX () - offsetPoint.x));
			System.out.println("Y- K : " + getY () + (e.getY () - offsetPoint.y));
			
			System.out.println("X- Koordinate des Bildes : " + this.getLocation().getX());
			System.out.println("Y- Koordinate des Bildes : " + this.getLocation().getY());
			
		}
	}

	protected void processMouseEvent (MouseEvent e) {
	
		// click on Tile
		if(e.getID() == MouseEvent.MOUSE_PRESSED) {
			
			if(this.getParent() instanceof JLayeredPane) {
				// get original layer 
				originalLayer = JLayeredPane.getLayer(this);

				// drag tile layer 
				((JLayeredPane) getParent ()).setLayer (
						this, JLayeredPane.DRAG_LAYER.intValue ()
				);
				
				// determine offset - mouse point depends on pic
				offsetPoint = new Point(e.getPoint ().x,
										e.getPoint ().y);
			}
			
		// release tile
		}else if(e.getID () == MouseEvent.MOUSE_RELEASED) {

			if(getParent () instanceof JLayeredPane) {
			// back to originLayer
			((JLayeredPane) getParent()).setLayer(this, originalLayer);

			// check collision with another Tile
			final TouchLocation touchLoacation = checkCollision();

				switch(touchLoacation){
					case NONE : 
						break;
					case TOP : //DragAndDropPanelsDemo.showOPtionDialog();
						break;
					case BOTTOM:
						break;
					case RIGHT:
						break;
					case LEFT:
						break;
				}
				
			// no dragging anymore
			offsetPoint = null;
			}
		}
	}
	
	public void paintComponent(Graphics g) {
		super.paintComponent(g);
		Graphics2D g2 = (Graphics2D) g;
		// zeichnen
		g2.drawString("x-Kooridnate: " + this.rectangle.x,10,10);
		g2.drawString("y-Kooridnate: " + this.rectangle.y,10,25);
		g2.drawRect(this.rectangle.x,this.rectangle.y, this.rectangle.width, this.rectangle.height);
}
}
```


Hier wo ich das teste:


```
public class DragAndDropPanelsDemo extends JFrame {
	static DragableTile e = null;
	static DragableTile f = null;
	static DragableTile g  = null;
	Bootstrap b = new Bootstrap();
	static JLayeredPane layeredPane;
	
	
	static ArrayList<DragableLabel> list = new ArrayList<DragableLabel>();
	
	ImageManager a = ImageManager.getInstance();
 public DragAndDropPanelsDemo () {

   JPanel zweitesPanel = new JPanel ();
   zweitesPanel.setLayout(null);

   
   
   
   
   
   
   
   
   
   
   layeredPane = new JLayeredPane();
   layeredPane.setLayout(null);
   //layeredPane.setPreferredSize(new Dimension(300,300));
// public DragableLabel(String name, Color farbe)

   e = new DragableTile(1, 1, 0);
   layeredPane.add(e,JLayeredPane.DEFAULT_LAYER);
   
   //e.setBounds(0,0,e.imageWidth,e.imageHeight);
   
   
   layeredPane.setBounds(0,0,500,500);
   
   
   
   
   f = new DragableTile(1, 1, 0);
   
   
   
   layeredPane.add(f,
           new Integer (
             JLayeredPane.DEFAULT_LAYER.intValue()
             +1));
   
   //f.setBounds(0,0,e.imageWidth,e.imageHeight);
   
   
   
   g = new DragableTile(1, 1, 0);
   
   layeredPane.add(g,
           new Integer (
             JLayeredPane.DEFAULT_LAYER.intValue()
             +1));
   
  // g.setBounds(0,0,e.imageWidth,e.imageHeight);
   
   DragableTile.dragableTileList.add(e);
   DragableTile.dragableTileList.add(f);
   DragableTile.dragableTileList.add(g);
   zweitesPanel.add(layeredPane);
 
//   g = new DragableLabel(a.getImageIcon("a.jpg"), Color.BLUE);
//   layeredPane.add(g,
//                new Integer (
//                  JLayeredPane.DEFAULT_LAYER.intValue()
//                  +2));


//	System.out.println(e.rectangle.toString());
//	System.out.println(f.rectangle.toString());
//	//System.out.println(g.rectangle.toString());



   getContentPane().add(zweitesPanel);
   setVisible(true);
 }

 public static void main (String[] argv) throws Exception {
	  System.out.println("Starting Drag And Drop Example ...");
	  DragAndDropPanelsDemo mainFrame = new DragAndDropPanelsDemo();
	  mainFrame.setSize(400, 400);
	  mainFrame.setLocation(100,100);
	  mainFrame.setTitle("Drag And Drop Example");
	  mainFrame.setVisible(true);
 }
```

Es ist kein KSKB... nur ein Ausschnitt, kann gerne aber ein besipiel anhängen.

Aber hoffe das ihr mein fehler seht.
Habe viel ausprobiert ...

danke vielmals


----------



## Volvagia (17. Apr 2011)

Ja, häng bitte ein Beispiel dran.
btw. sollte es statt Tile nicht eher Tilde heißen?


----------

