# Drag & Drop in Swing (createTransferable)



## mitzy (14. Jan 2009)

Hallo alle,

ich hab ein paar Fragen zu Drag & Drop in Swing. 

Und zwar schreibe ich eine Applikation, mit der man Gepäckförderbänder modellieren und das Transportieren von Gepäckstücken darauf simulieren kann. Hier ein Screenshot der GUI: http://scriptkiddy.de/gui.png

Nun soll man aus der Seitenleiste die Bausteine auf das Raster draggen & droppen können. Bei den Componenten handelt es sich links um modifizierte JButtons und rechts um ein Array aus modifizierten JLabels.

Um meine JButtons drag-fähig zu machen, habe ich nun folgenden Code hinzugefügt, den ich anhand eines Beispiels unseres Profs gebastelt hab.


```
//drag and drop
//bgerade ist der modifizierte JButton, der die Gerade darstellt 

		bgerade.setTransferHandler(new TransferHandler() {
			@Override
			public int getSourceActions(JComponent c) {
				return COPY;
			}
			
			@Override
			protected Transferable createTransferable(JComponent c) {
				String test = "test";
				System.out.println("createTransferable mit Inhalt: "+test);				
				return new StringSelection(nutzlast);
			}
		});
		
		MouseListener ml = new MouseAdapter() {
			public void mousePressed(MouseEvent me) {
				JComponent c = (JComponent)me.getSource();
				TransferHandler th = c.getTransferHandler();
				th.exportAsDrag(c, me, TransferHandler.COPY);
			}
		};
		
		bgerade.addMouseListener(ml);
		//ende
```

In der createTransferable Methode wird jetzt ja aber nur ein String übergeben. Vom Prof gab es noch ein weiteres Beispiel, bei dem ein eigenes Objekt übergeben wurde, und zwar folgendes:


```
/* 
			 * Wieder Transferobjekt bauen, diesmal mit
			 * eigener Klasse MeineTransferDaten (und
			 * die dann in DataHandler wickeln)
			 */
			@Override
			protected Transferable createTransferable(JComponent c) {
				System.out.println("imageDragLabel: createTransferable");
				DataHandler dh = new DataHandler(new MeineTransferDaten(getNachricht(), getZaehler()), MeineTransferDaten.getFlavor().getMimeType());
				return dh;
			}
```

Nun habe ich aber das Problem, dass mir Eclipse den DataHandler rot unterstreicht, weil es den folgenden Import nicht kennt:


```
import javax.activation.DataHandler;
```

Ich bin MacUser, habe daher nur Java 5. Ist das package javax.activation erst ab Java 6 vorhanden? Ich konnte dazu nicht wirklich was finden bei google. Nur, dass dieses Package wohl in der J2EE vorhanden ist, nicht aber in der J2SE.

Zurück zu meiner ursprünglichen Frage: die Methode createTransferable muss ja nicht zwangsläufig einen DataHandler zurückgeben, oder? Könnte ich nicht eine eigene Klasse schreiben, die Transferable implementiert und diese dann ohne DataHandler zurückgeben?

Wäre klasse, wenn mir jemand helfen könnte!


----------



## Marco13 (14. Jan 2009)

http://java.sun.com/javase/6/docs/api/javax/activation/DataHandler.html -> *Since: 1.6*
Das hat mich auch schon genervt.

Aber ja: Man kann ein eigenes Transferable erstellen. Dazu findet man (mit Forensuche und Web) auch Beispiele. Oder gibt's eine konkrete Frage dazu?


----------



## Guest (14. Jan 2009)

Alternativ jagst du dein Objekt vorher durch einen Serialisierer dann kannst du das Drag n Drop mit Strings nutzen und deserialisierst es nacher wieder:


```
public class Serializer {
	public static String serializeToString (ImgTxt objectToWrite)throws IOException, ClassNotFoundException {

		ByteArrayOutputStream out = new ByteArrayOutputStream();
		ObjectOutputStream oos = new ObjectOutputStream( out );
		oos.writeObject( objectToWrite );
		oos.close();
		out.close();
		
		// String ausgeben
		String output = Base64.encodeBytes( out.toByteArray() );

		return output;
	}

	public static ImgTxt deserializeFromString (String serializedObject)throws IOException, ClassNotFoundException {

		byte[] pick = Base64.decode(serializedObject);
		InputStream in = new ByteArrayInputStream(pick);
		ObjectInputStream ois = new ObjectInputStream(in);
		ImgTxt deserializedObject = (ImgTxt) ois.readObject();
		ois.close();
		in.close();

		return deserializedObject;
	} 
}
```


----------



## Gast (14. Jan 2009)

Den Base64 De/Encoder gibts übrigens hier: http://iharder.net/base64


----------



## kmt (29. Jan 2009)

hmm ich habe die erste Version, also die mit 

```
protected Transferable createTransferable(JComponent c) {
            String test = "test";
            System.out.println("createTransferable mit Inhalt: "+test);            
            return new StringSelection(nutzlast);
         }
```
 auch ausprobiert, aber beim Klicken auf einen JButton bleibt -vermutlich der Windowmanager- stehen und es wird auf irgendetwas gewartet.. (die Maus l"asst sich noch bewegen, aber alle Fenster reagieren nicht auf Mause oder Tastatur).

Erst wenn ich die Applikation kille, reagieren die Fenster wieder.

woran kann das liegen?

gru"ss, kmt


----------



## kmt (29. Jan 2009)

hmm geht doch.. vergesst bitte mein post von eben..

Aber wie kann man das bein Verschieben angezeigte Bild ändern? Ich würde da gern ein Image anzeigen. Geht das?


----------



## Ebenius (29. Jan 2009)

kmt hat gesagt.:
			
		

> Aber wie kann man das bein Verschieben angezeigte Bild ändern? Ich würde da gern ein Image anzeigen. Geht das?


Geht, glaub ich, über den TransferHandler: getVisisibleRepresentation().


----------

