# Überlappung zweier Komponenten



## Sunchezz (2. Dez 2011)

Hallo liebe Leutchens!

Ich wende mich nun mal in einem neuen Thread an euch, da das ursprüngliche Thema sich meiner Meinung nach erledigt hat. Das neue ist zwar ähnlich aber nun ja!
Vielleicht ist ja eine aktuellere Beschreibung doch mehr hilfreich.
Wer sich den alten Thread noch anschauen will um die gesamtproblematik mehr zu verstehen:
altes Thema

Nun zum eigentlichen Problem:

Ich möchte eine Component in einem Container mit der Maus bewegen.
Wenn diese Component nun aber selbst ein richtiger Container, wie z.B. ein ScrollPane oder so ist, kann ich sie ja nicht greifen, da der MouseListener natürlich nur die innenliegende Komponente (eventuell eine Table oder so) als Quelle erkennt.
Demnach kann ich dieses Element nicht verschieben.

Mein bisher einfachster Ansatz:
Aus der Component temporär ein Bild machen, dadurch werden auch alle anderen Komponenten dargestellt, und danach kann wieder alles normal dargestellt werden.
Leider habe ich das mir unerklärliche Phänomen, das wenn ich diese BildComponent verschiebe und dabei über andere Komponenten ziehe, das das Bild dann flackert (genauer gesagt werden die darunterliegende Component und das Bild abwechselnd dargestellt)

Eine vielleicht nich ganz unwichtige Info:
Das Panel welches die verschiebbaren Komponenten enthält, liegt selbst in einem LayeredPane.
wird eine Komponente ausgewählt, wird sie Kurzfristig aus dem eigentlichen Panel entfernt, auf ein durchsichtiges Panel geadded. Dann wird das durchsichtige Panel im LayeredPane nach vorne geholt, und die Komponenten sind ganz normal Sichtbar. Nach dem Loslassen, das ganze wieder andersrum.
Der Grund für zwei Panels ist, das ich das ganze innerhalb eines Layouts mache und beim Verschieben eine Vorschaukomponente dargestellt werden soll, wo die Komponente landet wenn man loslässt ( ich glaub ich musses nicht erwähnen, aber ich tus trotzdem. Würde ich es in einem Panel machen würde die Layoutaktualisierung die Komponente die man grade zieht bei jeder Bewegung flackernd wieder an den Ursprungsort zurückspringen lassen)

Was mich an dem ganzen so verwirrt: Wenn ich anstatt dem LayeredPane ein Panel, und als zweitPanel, das standard GlassPane nehme, funktionierts wunderbar flackerfrei!

Ich hoffe das jemand eine Idee hat woran das liegt!


----------



## André Uhres (5. Dez 2011)

Sunchezz hat gesagt.:


> Wenn diese Component nun aber selbst ein richtiger Container, wie z.B. ein ScrollPane oder so ist, kann ich sie ja nicht greifen
> ...
> Mein bisher einfachster Ansatz: Aus der Component temporär ein Bild machen



Für mich macht das keinen wesentlichen Unterschied, denn auf den Container zugreifen musst Du ja in beiden Fällen, oder wie meinst Du das?

Gruß,
André

PS: das Flackern könnte damit zusammenhängen, dass die "mouseDragged" Ereignisse in Bezug auf die Komponente erzeugt werden und die Komponente sich gleichzeitig mit der Maus bewegt.


----------



## vanny (5. Dez 2011)

Ich denke auch, dass das Flackern vom mouseDragged-Event herrührt.
Ich würde mir bei MousePressed eine Flag setzen und dann einen seperaten Thread starten, der deine Bildverschiebungsgeschichte regelmäßig neu zeichnet.
Bei MouseDragged geschieht das ja immer nur dann, wenn du die Maus bewegst.

Gruß Vanny


----------



## Sunchezz (5. Dez 2011)

Ui, danke schonma für die Antwort, dachte schon es kommt nichts mehr!



André Uhres hat gesagt.:


> Für mich macht das keinen wesentlichen Unterschied, denn auf den Container zugreifen musst Du ja in beiden Fällen, oder wie meinst Du das?



Naja, um eine Komponente zu greifen, muss ich sie ja direkt anfassen ("beklicken"), und im falle einer Table (mit ScrollPane), möchte man ja eigentlich die Table verschieben. Da die Table ja aber eine Subkomponente ist, ist sie ja weiterhin aktiv, und reagiert auf sämtliche Mausklicks (Zellenselektion) und daher interessierts das ScrollPane ja wenig das der Nutzer eigentlich das ganze "Paket" verschieben will.



André Uhres hat gesagt.:


> PS: das Flackern könnte damit zusammenhängen, dass die "mouseDragged" Ereignisse in Bezug auf die Komponente erzeugt werden und die Komponente sich gleichzeitig mit der Maus bewegt.



Nun ja, das witzige ist ja, das wenn ich alles, statt mit einem LayeredPane und einem zweitpanel, mit dem FrameGlassPane mache, alles wunderbar flüssig läuft. Selbe listener und alles, ich füge die Temporär zu verschiebene Komponente nur aufs Glasspane und setzte bei MouseDragged die Location neu, so auch jetzt. Und nu flackerts!


Aber trotzdem danke!


----------



## André Uhres (5. Dez 2011)

Dass man die "Scrollpane" nicht immer greifen kann, war mir schon klar (obschon es in der Ecke unten rechts immer dann gehen würde, wenn beide "Scrollbars" sichtbar sind). Um ein Bild zu erzeugen, musst Du aber ebenfalls zuerst wissen, was der Benutzer verschieben will: das Problem bleibt also dasselbe.

Der Unterschied bei deinen beiden Implementationen wo eine flackert und die andere nicht, könnte vielleicht darin bestehen, dass die MouseListener unterschiedlich eingesetzt werden.


----------



## Sunchezz (5. Dez 2011)

André Uhres hat gesagt.:


> Dass man die "Scrollpane" nicht immer greifen kann, war mir schon klar (obschon es in der Ecke unten rechts immer dann gehen würde, wenn beide "Scrollbars" sichtbar sind). Um ein Bild zu erzeugen, musst Du aber ebenfalls zuerst wissen, was der Benutzer verschieben will: das Problem bleibt also dasselbe.



Nun ja, in der ersten Version geh ich erstmal davon aus das Verschiebungen nur von "top-Level-elementen" in dem eigentlichen VerschiebePanel nutzbar sind. Also wäre es in jedem Fall immer die Table + ScrollPane die man verschieben will. Der standard user weiß ja nich das das eigentlich 2 Komponenten sind^^

Und was die Bilderzeugung angeht, die führ ich schon aus wenn in dem Panel der "Config button" gedrückt wird. Da werden sofort alle ScrollPanes und JPanels usw. zu Bildern gemacht!

Kleiner Hinweis zu ScrollPane, an der Border ist sie immer zu packen 



André Uhres hat gesagt.:


> Der Unterschied bei deinen beiden Implementationen wo eine flackert und die andere nicht, könnte vielleicht darin bestehen, dass die MouseListener unterschiedlich eingesetzt werden.



Nein, das kann meiner Meinung einfach nicht sein.
Der einzige Unterschied ist wie gesagt, das ich innerhalb des Listeners anstatt

```
glasspane.add(selectedComponent);
```


```
secondPanel.add(selectedComponent);
```
... nutze.

Kann es irgendwas mit dem LayeredPane zu tun haben, oder mit der Art wie ich von der Component ein Bild mache?

Mit den anderen normalen Komponenten existiert dieses Problem ja nicht. nur wenn ein selbstgemachtes Bild ins Spiel kommt.
Also wenn nen normaler Button über das Bild gezogen wird, oder andersrum.


mit der Klasse erstelle ich die Bilder von den Komponenten:

```
package jls.tests.gui;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;

import javax.swing.JComponent;

public class ComponentCopyPicture extends JComponent {

	private static final long serialVersionUID = 1992007953073696720L;
	private Image img;
	
	public ComponentCopyPicture(Component c) {
		this.img = getComponentPicture(c);
		oldComponentPosition = c.getParent().getComponentZOrder(c);
	}
	
	public ComponentCopyPicture(Image img) {
		this.img = img;
		int w = img.getWidth(this);
		int h = img.getHeight(this);
		setPreferredSize(new Dimension(w, h));
	}	

	protected void paintComponent(Graphics g) {
		g.drawImage(img, 0, 0, this);
	}
	
	protected Image getComponentPicture(Component c) {
		BufferedImage img = new BufferedImage(c.getWidth(),
				c.getHeight(), BufferedImage.TYPE_INT_RGB);
		img.flush();
		c.paint(img.getGraphics());
		return img;
	}
}
```


----------



## André Uhres (6. Dez 2011)

Sunchezz hat gesagt.:


> Nun ja, in der ersten Version geh ich erstmal davon aus das Verschiebungen nur von "top-Level-elementen" in dem eigentlichen VerschiebePanel nutzbar sind. Also wäre es in jedem Fall immer die Table + ScrollPane die man verschieben will. Der standard user weiß ja nich das das eigentlich 2 Komponenten sind^^



In der "Bild"-Version gehst Du ja sicher von derselben Annahme aus. Wie gesagt, für mich macht das keinen wesentlichen Unterschied, denn auf den Container zugreifen musst Du ja in beiden Versionen. 

Dein Problem ist wohl gar nicht, dass der Container nicht greifbar ist, wie Du behauptest, sondern etwas, was man sich nicht so richtig vorstellen kann. 

Versuch mal ein KSKB zu machen. KSKB bedeutet: Kurzes, Selbständiges, Kompilierbares Beispiel. Ein KSKB vorzubereiten kostet Anstrengung. Der Lohn: schnellere Lösung des Problems. Oft führt es dazu, dass man die Lösung selbst findet, ohne etwas zu posten, weil man dann nämlich gezwungen ist, das Problem auf das Wesentliche zu reduzieren und somit die Lösung leichter zu finden ist.


----------



## Sunchezz (6. Dez 2011)

André Uhres hat gesagt.:


> Dein Problem ist wohl gar nicht, dass der Container nicht greifbar ist, wie Du behauptest, sondern etwas, was man sich nicht so richtig vorstellen kann.


Das versteh ich nun garnicht.
Wie gesagt, mit einem Bild find ichs eigentlich am besten.



Vielen dank, was ein kskb ist weiß ich.
Das Problem ist, das mein momentanes Projekt ein reines KSBK ist...
Ich könnte dir höchstens die Jar schicken mit source, da es doch um die 6 umfangreichen Klassen sind.

Ich werde aber veruchen es alles noch mehr zu kürzen! -.-


----------



## Sunchezz (6. Dez 2011)

Sooooo...
Hat sich erledigt, funktioniert jetzt alles!
Ich hatte ein Validate zu viel drin -.-

Tschuldigung!


----------



## André Uhres (7. Dez 2011)

Du sagtest, Dein Problem sei, dass der Container nicht greifbar ist. Wie Du das mit einem Bild lösen kannst, das versteh ich allerdings gar nicht.

Indem Du dich dann bemüht hast, Dein "KSKB" auf das Wesentliche zu reduzieren, hast Du den Fehler selbst gefunden (Glückwunsch, kommt allerdings öfter vor) und zudem hat der Fehler anscheinend auch gar nichts mit dem Bild zu tun!


----------



## Sunchezz (7. Dez 2011)

Der Container ist nach wie vor für mich in dem Sinne nicht greifbar, das eine Komponente darin(!) ist. Der Nutzer sieht nur eine Tabelle und möchte sie gerne an einen anderen Platz verschieben, weiß aber nicht, das er eigentlich das ScrollPane verschieben muss. Also klickt er munter auf der Tabelle rum, und anstatt das sie zur Bewegung "freigegeben" ist (das ist ja nur das ScrollPane), wird einfach nur in der Tabelle eine Zelle selektiert wie gewöhnlich. Indem ich aus der ScrollPane samt inhalt nen Bild mache, und dieses wie eine JComponent behandle, erreiche ich das es für den nutzer so aussieht als verschiebt er "einfach nur" die Tabelle!


Muss dich leider enttäuschen, es lag nicht am Kskb 
Und ja, es lag nicht am Bild, sondern am validate(), obwohl ich das immernoch nur teilweise verstehe... 
Trotzdem danke für die Hilfe!


----------



## André Uhres (7. Dez 2011)

Klingt widersprüchlich, aber damit muss ich jetzt wohl leben .

Gruß,
André


----------



## Sunchezz (8. Dez 2011)

Was genau, das erste oder das zweite? 
Kanns gerne noch erklären, ansonsten mach ich zu


----------

