# Schichten bei Jpanel



## sawicada (25. Nov 2008)

Hallo erstmal Ich mit meiner Praktikumsgruppe haben ein kleines Program zur Modelleisenbahn zu erstellen und ueberlegen wir mit dem Zeichnen der Simulationsoberflaeche. Die Frage ist: Gibt es einen fertigen Bibliotheke die eine Schichtenweise aufgeteilten bild mallt? Wir brauchen auf dem JPanel ein Zug verschieben, dabei muss man aber immer das hintergrund von unten von der Zug neu mallen. Wenn man das nach schichten verteilt, dass der hintergrund bleibt und der zug ist auf eine durchsichtige oberflaeche aufgemallt dann waehre es viel einfacher und efektiver. Entschuldigung fuer meine Schreibweise, Deutsch ist nicht meine Muttersprache. Vielen dank fuer jede Hilfe

EDIT:
Wir nutzen NetBeans von 6.1 bis 6.5 und SWING Gui, JDK 6.0 update 10


----------



## Quaxli (25. Nov 2008)

Ihr könntet auf das JPanel die Oberfläche malen und auf die GlassPane den Zug, aber das ist prinzipiell umständlich.
Das einfachste ist, alles auf ein JPanel zu malen.


----------



## byte (25. Nov 2008)

Quaxli hat gesagt.:
			
		

> Das einfachste ist, alles auf ein JPanel zu malen.


Das wäre wohl die dämlichste Variante. 

@sawicada: Guck Dir JLayeredPane an. Alternativ gehts auch mit JXLayer von SwingX.


----------



## Quaxli (25. Nov 2008)

Was ist da wohl so furchtbar dämlich dran? Wenn Du mir schon dumm kommst, begründe es wenigstens. 

Einmal paint-Methode überschreiben muß sie auf jeden Fall um den Zug zu zeichnen. Und wenn Sie da davor noch ein Image mit der "Bodenplatte" malt, hat sie alles was sie braucht.


----------



## sawicada (25. Nov 2008)

Mir ist einfach wichtig dass es funktioniert und relativ einfach zu implementieren ist weil ich noch ein noob binXD Danke euch beiden fuer die Antworte aber kaempft nicht gegenseitig bitteXD Mein kleinen Problem ist nicht wert genug um Blutt zu vergiesen


----------



## byte (25. Nov 2008)

Quaxli hat gesagt.:
			
		

> Was ist da wohl so furchtbar dämlich dran? Wenn Du mir schon dumm kommst, begründe es wenigstens.


Welche Lösung führt wohl langfristig zu besserem Code: (i) die komponentenbasierte Lösung mittels JLayeredPane, wo jedes darzustellende Element als eigene JComponent implementiert wird oder (ii) Deine Lösung, wo der gesamte Code in einer Methode (paintComponent) ist und man alles mittels Java2D selbst implementieren muss (neu positionieren von Elementen, Resizing, Double Buffering, ...)?
Spätestens wenn Drag and Drop ins Spiel kommt, fliegst Du mit Deinem Lösungsansatz auf die Nase.


----------



## Quaxli (25. Nov 2008)

Wir sprechen schon noch über die Eisenbahnlösung (Bild mit Zug drauf, der bewegt wird).

Wenn Du wirklich jedes darzustellende Element als eigene JComponent implementieren willst (und damit den ganzen Overhead um ein paar Klötzchen für die Darstellung eines Zugs zu Malen): Meine Lösung. 

Zumindest für dieses Problem mit 'ner kleinen Animation.


----------



## byte (25. Nov 2008)

Quaxli hat gesagt.:
			
		

> Wenn Du wirklich jedes darzustellende Element als eigene JComponent implementieren willst (und damit den ganzen Overhead um ein paar Klötzchen für die Darstellung eines Zugs zu Malen): Meine Lösung.


Von welchem Overhead sprichst Du bitte? Lokomotive von JComponent ableiten und mit Hintergrund auf JLayeredPane packen. Dann kannst Du per setLocation den Zug beliebig positionieren. Der Implementierungsaufwand ist geringer als bei Deiner Lösung. Wenn Du das nicht siehst, tuts mir leid für Dich. :roll:


----------



## André Uhres (25. Nov 2008)

Er meint vielleicht, daß das Toolkit sich dann zusätzlich um überlappende Komponenten kümmern muss. Doch der Zug wird wohl nicht so schnell rasen, daß das ein Problem werden könnte.


----------



## Marco13 (26. Nov 2008)

byto hat gesagt.:
			
		

> Von welchem Overhead sprichst Du bitte? Lokomotive von JComponent ableiten [...] Der Implementierungsaufwand ist geringer als bei Deiner Lösung. Wenn Du das nicht siehst, tuts mir leid für Dich. :roll:



Oft gibt es zwei Möglichkeiten, wie man etwas machen kann: 
1. Einfach
2. Gut
(optional gibt es auch noch "einfach gut", aber das ist sehr selten :wink: ). Zum wiederholten male poste ich darum nun (einen Link auf) die Auflistung der 83 Gründe, warum man nicht "einfach mal so" von JComponent erben sollte:
http://www.java-forum.org/de/viewtopic.php?p=401218&highlight=#401218
Wenn du das als unbedeutend ansiehst, tuts mir leid für dich :wink:


----------



## byte (26. Nov 2008)

Du willst mir nicht ernsthaft weiss machen, dass Du versuchst JComponents zu vermeiden, weil sie 83 (größtenteils primitive) Member haben? ???:L

Die GUI meines derzeitigen Projekts besteht (grob geschätzt) aus einer vierstelligen Anzahl JComponents. Der Speicherverbrauch der GUI Komponenten liegt prozentual zu den Objekten des Datenmodells im einstelligen Prozentbereich.


BTW: Hättest Du Dir eine JComponent mal im Debugger angeguckt, dann wäre Dir im übrigen aufgefallen, dass der Großteil der (nicht primitiven) Member beim Instanzieren der JComponent *null* sind.


----------



## Marco13 (26. Nov 2008)

Ich kapier' deine Frage (und deine Aussage in diesem Zusammenhang) nicht. Wenn man einen 2D-Punkt speichern will, verwendet man dafür einen Point - und keine JComponent, obwohl "die ja auch eine Methode setLocation" hat. Man speichert, was man speichern muss, und nicht mehr. Man bietet die Methoden an, die man anbieten muss, und nicht mehr. Konsequent (und, das gebe ich zu, etwas übertrieben plakativ) weitergeführt hieße das ja, eine riesige Klasse zu erstellen, die ALLE Fields und ALLE Methoden hat, die man IRGENDWO mal braucht - und JEDE andere Klasse würde von dieser Klasse erben, nur die Fields und Methoden verwenden, die gerade (für die spezielle, erbende Klasse) notwendig sind, und die anderen ignorieren... Das _geht_ natürlich, ja... :roll:

Dass dein GUI aus vielen Components besteht, wundert mich jetzt nicht so.... Das ist nicht sooo unüblich. Aber sein "Datenmodell" (sofern man (speziell in bezug auf die ursprüngliche (Anfänger)frage) diesen hochtrabenden Begriff verwenden will) aus JComponents aufzubauen, ist IMHO zurückhaltend formuliert ziemlicher Unfug....


----------



## byte (26. Nov 2008)

Hast Du überhaupt gelesen, worum es in diesem Thread geht? Es geht hier um die Darstellung eines Zuges auf einem festen Hintergrund. Die Position des Zuges soll veränderbar sein.

Es ist also alles andere als Unfug, diesen Zug als JComponent zu implementieren. Schließlich gehts hier um Darstellung innerhalb der GUI. Was Du jetzt von Datenmodell und Point faselst, ist mir echt schleierhaft!?

Versuchst Du jetzt krampfhaft irgendwie zu kontern, nur weil ich Dein "Axiom der bösen JComponent" entkräftet habe? :wink:


----------



## André Uhres (26. Nov 2008)

Wir können dazu auch mal folgendes bedenken:
Die Methode "Component#setLocation" bewirkt einen repaint, 
und zwar nur von dem Rechteck, das aktualisieren muss.
In "paintComponent" kann man dieses Rechteck mittels "getClipBounds" abfragen.
Der drawImage(..)-Aufruf kann dann so geschneidert werden, daß er nur den
Teil des Hintergrundbildes neu zeichnet, der sich mit dem Cliprechteck überschneidet:

```
@Override
    public void paintComponent(final Graphics g) {
        super.paintComponent(g);
        Rectangle r = g.getClipBounds();
        g.drawImage(img, r.x, r.y, r.width + r.x, r.height + r.y,
                r.x, r.y, r.width + r.x, r.height + r.y, null);
    }
```
So betrachtet mag es angebracht sein, diese und andere eingebaute Malmechanismen 
durch die Ableitung von JComponent zu nutzen :wink:


----------



## Marco13 (26. Nov 2008)

Das "Axiom der bösen JComponent" ist nicht entkräftet. Vielleicht liegt das daran, dass es niemand (in dieser Form) aufgestellt hat. Vielleicht liegt ein Problem nicht zuletzt darin: In der unpräzisen Aufgaben- bzw. Fragestellung, und in der unpäzisen Antwort. 

Ursprünglich ging es darum:

_haben ein kleines Program zur Modelleisenbahn zu erstellen ..._ und _...Simulationsoberflaeche..._

Was ich mal so interpretiere, dass sie ein Programm haben, mit dem sie ein (Daten)modell einer Modelleisenbahn erstellen können - wohlgemerkt, der Programmkern ist (meiner Interpretation nach) nicht, irgendwas zu zeichnen, sondern ein (Daten)modell zu erstellen, dass eine Modelleisenbahn repräsentiert, und auf dem dann Züge simuliert werden können. 

_...und ueberlegen wir mit dem Zeichnen der Simulationsoberflaeche [...] Wir brauchen auf dem JPanel ein Zug verschieben, ..._

Ja, damit man das ganze irgendwie hübsch anschauen und bedienen kann, braucht man natürlich auch ein GUI. Und in dem soll dann (innerhalb eines JPanels) ein Zug dargestellt werden. Mit dem GUI soll auch der Zug irgendwie verschoben werden können. OK. 
Aber wenn du nun sagst, 

_Lokomotive von JComponent ableiten_

klingt das, als sollte etwas höchst GUI-spezifisches in den Kern der Modellierungs- und Simulationssoftware eingebaut werden (der im Idealfall ja nichtmal weiß, dass es überhaupt ein GUI gibt!), und damit so etwas (in erster Näherung) abstrakt, einfach und "schlank" zu beschreibendes wie eine Lokomotive auf einmal eine focusTraversalPolicy enthält und Methoden anbietet wie "addComponentListener" :autsch: also zu 99% überflüssiger Firlefanz, von dem sie effektiv NICHTS braucht, außer vielleicht dem *Point* (siehe voriger Post), der ihre Position beschreibt, und den du dann mit setLocation verändern wolltest.

Vielleicht hatte ich die Aufgabenstellung falsch interpretiert. Vielleicht meintest du auch, dass er sowas wie einen "TrainRenderer extends JComponent" anbeiten sollte (in Analogie zum DefaultListCelllRenderer von Swing) - dann hatte ich deine Aussage falsch interpretiert (aber setLocation aufzurufen wäre dann ggf. garnicht nötig). Und ob letzteres in diesem Zusammenhang Sinn machen würde, kann man (ohne genauere Kenntnis der Ziele und Randbedinungen des Projektes zwar NICHT pauschal mit "Nein" beantworten, aber) zumindest in Frage stellen...

Das was du als "Axiom der bösen JComponent" überinterpretiert hattest, war nur eine Kritik an der allgemeinen Tendenz (speziell von Anfängern), ALLE "Entitäten" die irgendwann mal irgendwo gezeichnet werden sollen, von JComponent abzuleiten. Und wenn du meinst, dass das sinnvoll ist ... naja, wir können ja mal eine Umfrage starten :wink:


----------



## SlaterB (26. Nov 2008)

die Lokomotive selber muss ja nun nicht von JComponent abgeleitet werden, 
genauso gut kann es eine Klasse LokomotiveZeichner sein,

es stehen doch nur 'pixelhaftes Zeichnen im komplizierter update-Routine' und 'Vorteile von JComponent (wie Positionierung, Einbindung in repaint) nutzen' gegenüber, 
letzteres zwar verbunden mit paar KB Overhead, aber der ist doch unerheblich,

wie man die Lokomotive implementiert oder ob deren Position sonst noch durch einen einfachen Point beschrieben wird,
ist davon unabhängig


----------



## André Uhres (26. Nov 2008)

Man könnte die Threadüberschrift fast umändern in "Sch*l*ichten bei JPanel"  :lol:


----------



## byte (26. Nov 2008)

@Marco13: Ich weiss nicht ob Du einfach Langeweile hast oder was der Grund dafür ist, dass Du hier jetzt eine Grundsatzdiskussion anfängst. Es ist mir im Grunde auch egal. Der TE hat eine klare Frage gestellt. Im Gegensatz zu Dir habe ich sie beantwortet.



> Die Frage ist: Gibt es einen fertigen Bibliotheke die eine Schichtenweise aufgeteilten bild malt? Wir brauchen auf dem JPanel ein Zug verschieben, dabei muss man aber immer das hintergrund von unten von der Zug neu mallen. Wenn man das nach schichten verteilt, dass der hintergrund bleibt und der zug ist auf eine durchsichtige oberflaeche aufgemallt dann waehre es viel einfacher und efektiver.


----------



## Marco13 (26. Nov 2008)

Wenn ich der Meinung bin, das etwas (modulo irgendwelcher Mißverständnisse aufgrund einer unpräzisen Fragestellung und unpräziser Antworten) _grundsätzlich_ falsch angegangen wird, muss ich eben eine _Grundsatzdiskussion_ anfangen. (Ist so ein Zwang, aber mein Therapeut sagt, es wird schon besser). Wenn man aber dann man einen Thread rekapituliert... ("dämlichste Lösung", damit "fliegst du auf die Nase", "Hast Du überhaupt gelesen, worum es in diesem Thread geht?", "Ich weiss nicht ob Du einfach Langeweile hast" ... ) schafft man es manchmal, sich davon zu lösen - egal wie verlockend leicht es wäre, manchen Leuten mit ihren eigenen Flames eins reinzuwürgen.

Argumente hast du bisher keine gebracht, außer Andeutungen im Sinne von "das ist einfach" und "ich mache das auch so" (wobei zwischen beiden vielleicht sogar ein kausaler Zusammenhang besteht). Dass man View und Modell trennen soll, sollte dir klar sein. Wenn nicht, ist jede weitere Diskussion, die ich mit dir führen... sollte... sowieso unter meinem Nievau. Wenn jemand eine Frage nach einer Bibliothek zum Zeichnen eines Bildes stellt, und du dann nur einwirfst, man möge doch eine JLayeredPane verwenden und alles von JComponent erben lassen, was man zeichnen will, dann klingt das schon sehr fragwürdig (oder zumindest so, als hättest du die Frage SEHR viel anders verstanden als ich). Und vielleicht hilft das dem Fragesteller weniger, als mehrere Vorschläge, das Aufzeigen von Alternativen und Optionen, und insbesondere ein Abtasten und Hinterfragen dessen, was GENAU er denn eigentlich vorhat - zumindest um herauszufinden, ob er das schon selbst weiß. 

Es könnte ja angebracht sein, etwas spezielles, was man zeichnen will, von einer JComponent zeichnen zu lassen, und diese Component einem Zeichenbereich hinzuzufügen. Jeden "Sprite" durch eine JComponent darzustellen ist dagegen schon höchst fragwürdig, und sollte nicht als pauschale Empfehlung an einen Anfänger abgegeben werden. Aber nochmal das wichtigste: Im eigentlichen Datenmodell (und ich gehe davon aus, dass eine "Lokomotive" oder ein "Zug" zum Datenmodell gehört) haben JComponents nichts verloren. 

So. Jetzt kannst du noch sagen, dass ich arrogant und überheblich bin, und dass ich unrecht habe, und dass du tolle Porgramme mit vielen Components schreibst, und dass das ja auch alles funktioniert, und dann ist der Thread für mich persönlich zumindest...
	

	
	
		
		

		
			





 :wink:


----------



## André Uhres (27. Nov 2008)

Die ursprüngliche Fragestellung geht sicher mehr in Richtung Malen der View.
Die Trennung von View und Modell macht den Einsatz von Swing GUI Komponenten 
für die View wohl sinnvoll. 

Nehmen wir an, wir hätten erstmal nur eine Lokomotive. 
Dann würde für die View ein JFrame genügen, mit einem JPanel als Hintergrund 
und einem JLabel als Lokomotive. 
Das JPanel fügen wir einfach zum JFrame hinzu und das JLabel zum JPanel. 

Für das JLabel (Lokomotive) müsste man vielleicht noch eine intelligente 
"paintComponent" entwickeln, damit sich die Lokomotive auch immer schön 
in Fahrtrichtung dreht.

Die "paintComponent" für das JPanel mit dem Hintergrund habe ich oben schon gezeigt:
sie macht inelligenten Gebrauch vom Cliprechteck, damit nicht jedesmal der ganze
Hintergrund neu gezeichnet wird.


----------



## Quaxli (27. Nov 2008)

André Uhres hat gesagt.:
			
		

> Die ursprüngliche Fragestellung geht sicher mehr in Richtung Malen der View.
> Die Trennung von View und Modell macht den Einsatz von Swing GUI Komponenten
> für die View wohl sinnvoll.



Sagst Du..  Um mal auf meinen Ansatz zurück zu kommen, auch wenn er... - lassen wir das.

Ein JPanel brauchen wir ja auf jeden Fall, daß wir überschreiben, um das Hintergrundbild reinzupacken.
Damit haben wir schon eine Komponente im Einsatz, die von Haus aus doppelgepuffert ist. Was wäre jetzt da so schlimm dran, eine eigene kleine Klasse (die z.B. von Rectanlge erbt) da rein zu packen, die nach dem Hintergrundbild gezeichnet wird und wirklich nur das notwendigste enthält:
Das Bild/die Bilder für den Zug, eine Methode für irgendwelche Logiken, um das Ganze übersichtlich zu halten und eben eine paint-Methode, die sich auf die paint-Routinen beschränken kann. 
Und irgendwelche Clipping-Geschichten, sind bei dem bißchen Grafik (ein Bild, ein "Sprite") wirklich nicht notwendig.

Und schon unterscheidet sich das nicht mehr sehr viel von Deinem Ansatz, nur das Du eben ein JLabel verwendest, mit etlichen Dingen, die eigentlich nicht wirklich benötigt werden.


----------



## byte (27. Nov 2008)

Marco13 hat gesagt.:
			
		

> Dass man View und Modell trennen soll, sollte dir klar sein. Wenn nicht, ist jede weitere Diskussion, die ich mit dir führen... sollte... sowieso unter meinem Nievau.


View? Modell? Noch nie was von gehört. Was isn das? Lass mich mal an Deiner unendlichen Weisheit teilhaben... :roll:



> Wenn jemand eine Frage nach einer Bibliothek zum Zeichnen eines Bildes stellt, und du dann nur einwirfst, man möge doch eine JLayeredPane verwenden und alles von JComponent erben lassen, was man zeichnen will, dann klingt das schon sehr fragwürdig (oder zumindest so, als hättest du die Frage SEHR viel anders verstanden als ich).


Ein allerletztes Mal für diejenigen, die offenbar nicht lesen können: Es wurde danach gefragt, wie man Dinge *SCHICHTENWEISE* übereinander zeichnen kann. Wer da den Zusammenhang zu J*Layer*edPane nicht sieht, dem ist nicht mehr zu helfen, sorry.


----------



## Quaxli (27. Nov 2008)

Und wenn einem *NUR* JLayeredPane einfällt und alternative Lösungen wegge"flamed" werden, ist man auch nicht viel besser dran. Ebenfalls: Sorry.


----------



## André Uhres (27. Nov 2008)

Quaxli hat gesagt.:
			
		

> Und irgendwelche Clipping-Geschichten, sind bei dem bißchen Grafik (ein Bild, ein "Sprite") wirklich nicht notwendig.


Nicht selten nutzen wir standard APIs, von denen wir nur einen relativ kleinen Teil benötigen.
Es ist auch in Ordnung, die Swing Malmechanismen zu verstehen und zu nutzen, 
um korrekten und leistungsfähigen GUI Malcode zu schreiben, nicht wahr?


----------



## tfa (27. Nov 2008)

Das sehe ich genauso. Im Zweifel sollte man lieber ein schon existierendes Standardverfahren bzw. API/Lib verwenden als sich etwas selbst zusammenzufrickeln. Besonders wenn der  Grund bloß eine (vermeindliche) Performancesteigerung ist. Das fiele dann wohl unter "premature Optimization", und damit ist man meistens schlecht beraten. Wenn man sieht (vielleicht auch schon im voraus), dass die Standardlösung eher ungeeignet ist, kann man sich ja immer noch um eine Individuallösung kümmern.


----------



## Quaxli (27. Nov 2008)

@Andre:
Natürlich hast Du recht, aber doch Clipping doch nur wenn es notwendig ist, z. B. bei komplexen grafischen Darstellungen, wo sich z. B. aufgrund der Datenmenge das Zeichnen als sehr zeitaufwendig erweist. Bei dieser sehr einfachen Zeichenoperation ist es meiner Meinung nach unnötig.


----------



## byte (27. Nov 2008)

Quaxli hat gesagt.:
			
		

> Bei dieser sehr einfachen Zeichenoperation ist es meiner Meinung nach unnötig.



Genau auf diese Weise entsteht unwartbarer Code. Zunächst gibts wenige Anforderungen. Der Entwickler macht es schnell "irgendwie". Mit der Zeit wachsen die Anforderungen. Der anfangs noch recht übersichtliche Code mutiert zu Boilerplate Code.


----------



## André Uhres (27. Nov 2008)

Quaxli hat gesagt.:
			
		

> @Andre:
> Natürlich hast Du recht, aber doch Clipping doch nur wenn es notwendig ist


Für den Hintergrund würde ich Clipping dringend empfehlen, zumal die paintComponent-Methode 
ziemlich einfach und schon fertig ist (siehe oben).
Wenn wir  mit "setLocation" das JLabel bewegen, wird vom Toolkit automatisch repaint() 
mit Argumenten aufgerufen, die nur das Rechteck definieren, 
das aktualisieren muß (und nicht die keine-Argumente-Version, 
die die gesamte Komponente veranlasst, neu gezeichnet zu werden).

Was die Schichten betrifft: ein JPanel hat von Haus aus schon verschiedene "Schichten", die wir nutzen können:
Component, Border und Children werden standardmässig in dieser Reihenfolge übereinander gemalt.
Darüber hinaus hat jedes "Child" wiederum eine eigene "Schicht", die wir mit 
Container#setComponentZOrder "umschichten" können, wenn wir das wollen.


----------



## Marco13 (27. Nov 2008)

Hach, ich kann nicht widerstehen. 

Meiner Ansicht nach war ein wichtiger (wenn auch nicht explizit "genannter") Aspekt der ursprünglichen Frage, WIE die Verbindung zwischen den zugrundeliegenden Modelldaten und dem Zeichnen hergestellt werden soll. Diese Verbindung durch Vererbung herzustellen hatte ich ja schon zu genüge kritisiert. Aber tun wir mal so, als wäre das sinnvoll.

Ich habe irgendwie das Gefühl, dass hier ENTWEDER ein Haufen Bockmist erzählt wird, ODER ich etwas grundsätzlich falsch verstanden habe. Da ersteres sich auf Personen beziehen müßte, bei denen ich nicht glaube, dass es zutrifft, gehe ich mal von letzterem aus, und versuche deswegen, etwas konkreter zu werden. 

Man hat z.B. (nur zur Klärung (für mich, der ich schwer von Begriff bin)) sowas

```
class Modelleisenbahn
{
    List<Schiene> schienen = ...
    List<Lokomotive> loks = ...

    void fahre()
    {
        Für alle Loks sowas wie 
            lok.setPosition(old.x + time * movement.x, old.y + time * movement.y);
            lok.setOrientation(computeFromTrail());
    }
}

class Schiene
{
    List<Point oder Line2D oder so> verlauf = ...
}

class Lokomotive
{
    Point position = ...
    double fahrtrichtungsWinkel = ...
}
```

Wenn das ganze nun visualisiert werden soll, wie soll das dann gemacht werden? So: ?  ???:L   

```
class SchienenModell extends JPanel 
{
    List<Point oder Line2D> schienen = ...
    List<Lokomotive> loks = ...

    public SchienenModell()
    {
        setLayout(null);
        add(loks.get(0 bis n));
        add(schienen.get(0 bis n));
    }

    void fahre()
    {
        Für alle Loks sowas wie 
            lok.setLocation(old.x + time * movement.x, old.y + time * movement.y); // setLocation von JComponent
            lok.setOrientation(computeFromTrail());
    }

    public void paintComponent(Graphics g)
    {
        maleAlleSchienen(g); // Schicht 0

        super.paintComponent(g); // Male alle Loks
    }
}

class Lokomotive extends JComponent
{
    // Point position = ... // Fällt weg, da JComponent....

    double fahrtrichtungsWinkel = ...

    public void paintComponent(Graphics g) {... malt eine Lok... }
}
```
???:L 

(Mal abgesehen von so interessanten Fragen wie: Was passiert, wenn die Position einer Lok mit zwei *float*-Werten gespeichert ist - setLocation... äh.. geht dann nicht).

@André Uhres:
_Für das JLabel (Lokomotive) müsste man vielleicht noch eine intelligente
"paintComponent" entwickeln, damit sich die Lokomotive auch immer schön
in Fahrtrichtung dreht. _

Wenn man die paintComponent des für die Lokomotive "intelligent" macht, um die Lokomotive immer in Fahrtrichtung auszurichten, dann muss man doch zwangsläufig auch ausrechnen, wie groß das Label sein muss. Man muss also (in der oben angedeuteten "fahre"-Methode - die Teil der Simulation ist) auf Basis der akutellen Position, der Fahrtrichtung und der Abmessungen der Lok ihre "Bounding Box" bestimmen, um diese dann mit setBounds auf das Label anzuwenden. D.h. jedes Mal, wenn die Simulation einen Schritt macht, muss man mal kurz in den EDT wechseln, und dort die Locations und Bounds von etlichen JComponents neu berechnen und setzen. (Was alles repaints und ggf. viele ComponentEvents auslöst und so...).

In bezug auf das Clipping: Wenn man keine JComponents verwendet, kann man (optional(!)) die Bounding Box auchrechnen - um danach ein "repaint" aufzurufen, das sich NUR auf den Bereich bezieht, der sich geändert haben kann, um ggf. das Zeichnen effizienter zu machen - wenn man JComponents verwendet, MUSS man es praktisch machen. Der Aufwand ist in beiden Fällen der gleiche. Nur muss man das Clipping, wenn man es selbst macht, nicht implizit durch ein setBounds eine JComponent (im EDT) "herbeiwursten", sondern kann es direkt beim Berechnen des neuen Zustands berücksichtigen.

Hm. Aber velleicht haben wir nur unterschiedliche Ansätze, Vorstellungen und Zielsetzungen und so...


----------



## byte (27. Nov 2008)

Marco13 hat gesagt.:
			
		

> Meiner Ansicht nach war ein wichtiger (wenn auch nicht explizit "genannter") Aspekt der ursprünglichen Frage, WIE die Verbindung zwischen den zugrundeliegenden Modelldaten und dem Zeichnen hergestellt werden soll. Diese Verbindung durch Vererbung herzustellen hatte ich ja schon zu genüge kritisiert. Aber tun wir mal so, als wäre das sinnvoll


Darf ich mal fragen, wie Du darauf kommst, dass hier nach der Verbindung zwischen Modell und View gefragt wurde? Ich lese überhaupt nichts dergleichen aus dem Eingangspost raus. Die Frage des TEs dreht sich ausschließlich ums Zeichnen. Und genau darauf bezieht sich auch meine Antwort.
Natürlich implementiert man Datenmodell und Business Logik *NICHT* in einer JComponent. Das stand hier nie zur Diskussion und das habe ich auch nie propagiert. Offenbar hast Du das frei reininterpretiert.

Aber um trotzdem mal auf dieses Offtopic-Thema einzugehen: 

Wenn ich ein Business Object Lokomotive schreibe (das ist natürlich ein POJO), dann hat dort View-Logik überhaupt nichts verloren. Eine paintComponent(...) im Datenmodell ist gelinde gesagt dämlich. Technische Details haben in Fachobjekten nichts zu suchen, weil man damit das Fachobjekt an eine API bindet. Was machst Du, wenn Du später das Fachobjekt z.B. in Kombination mit einem SWT- oder Webclient wiederverwenden willst? Dann ist Dein Fachobjekt mit Swing-Code verseucht.

Viel naheliegender ist, zusätzlich zum Fachobjekt Lokomotive ein View-Objekt LokomotiveComponent von einer JComponent abzuleiten, das sämtliche View-Logik enthält, um eine Lokomotive in einem Swing-Client zu visualisieren. Und genau darauf bezog sich meine Antwort mit der Lokomotive extends JComponent.

Da aber explizit nur nach dem schichtenweisen Malen gefragt und mit keinem Wort MVC erwähnt wurde, bin ich auch nur darauf eingegangen, anstatt hier essayartig mein Wissen über Dinge zu verbreiten, nach denen nicht mal gefragt wurden. :roll:


----------



## André Uhres (27. Nov 2008)

Für die drehbare Lokomotive sollten wir darauf achten, 
daß im JLabel genügend Raum zum Drehen ist. 
Die “setLocation” können wir relativ zum Zentrum machen.


----------



## Marco13 (27. Nov 2008)

byto hat gesagt.:
			
		

> Lokomotive von JComponent ableiten





			
				Marco13 hat gesagt.:
			
		

> ...klingt das, als sollte etwas höchst GUI-spezifisches in den Kern der Modellierungs- und Simulationssoftware eingebaut werden....
> ...
> Vielleicht meintest du auch, dass er sowas wie einen "TrainRenderer extends JComponent" anbeiten sollte





			
				SlaterB hat gesagt.:
			
		

> die Lokomotive selber muss ja nun nicht von JComponent abgeleitet werden,
> genauso gut kann es eine Klasse LokomotiveZeichner sein,





			
				byto hat gesagt.:
			
		

> Natürlich implementiert man Datenmodell und Business Logik *NICHT* in einer JComponent. Das stand hier nie zur Diskussion und das habe ich auch nie propagiert. Offenbar hast Du das frei reininterpretiert.



Wie du oben siehst, STAND das zur Diskussion - und ich hatte ziemlich deutlich gesagt, dass dass, was DU gesagt hattest, so KLINGT, als hättest du etwas derartiges vor, und ich hatte auch schon indirekt gefragt, ob ich dich diesbezüglich mißverstanden hatte - was du aber nicht verneint hast, sondern ignoriert und mit Kommentaren zu potentieller Langeweile+Grundsatzdiskussion weggeflamt.



			
				byto hat gesagt.:
			
		

> Viel naheliegender ist, zusätzlich zum Fachobjekt Lokomotive ein View-Objekt LokomotiveComponent von einer JComponent abzuleiten



Ich hatte es TrainRenderer genannt, SlaterB hat es LokomotiveZeichner genannt, du nennst es LokomotiveComponent - das war alles schon aufgekommen. (Die Frage, ob ICH gelesen habe, worum es in diesem Thread geht, wirkt jetzt schon seltsam). Da du aber (trotz meines _gezielten_ Nachhakens genau in bezug auf diesen Punkt!!!) bisher NICHT explizit verneint hast, dass du mit deiner ursprünglichen Aussage "_Lokomotive von JComponent ableiten_" eine Verdengelung von Business- und View-Logik propagieren wolltest, kam diese teilweise ziemlich unsachliche Diskussion zustande. JETZT hast du es gesagt:



			
				byto hat gesagt.:
			
		

> ...LokomotiveComponent, das sämtliche View-Logik enthält, ... Und genau darauf bezog sich meine Antwort mit der Lokomotive extends JComponent.



Ja, gut. Dann sind wir ja einer Meinung  Und alles ist wieder gut 

Man kann (MUSS) aber davon ausgehen, dass ein Anfänger die lapidare Aussage "_Lokomotive von JComponent ableiten_" NICHT so interpretiert, wie du sie jetzt (ausführlicher, und im Zuge einer essayartigen Verbreitung deines Wissens, nachdem du nicht gefragt wurdest :wink: ) nochmal klargestellt hast. Wenn du einfach nur schreibst "_Lokomotive von JComponent ableiten_" dann wird sich dieser Anfänger sicher nicht denken: "Hey, ich hab ein POJO-Businessmodel das vielleicht mal in einer API über SWT in mit einer anderen View-Logik angeboten werden soll", sondern er wird bei seiner (Business-Klasse) "Lokomotive" einfach ein "extends JComponent" dahinterschreiben - und dann haben wir (sic!) den Salat.

Also: Manchmal ist eine ausführliche Antwort besser, auch wenn man (vielleicht auch aus seinem eigenen Wissen heraus, und davon ausgehend, dass bestimmte Dinge für alle Welt (einschließlich Anfängern) selbstverständlich sind) glaubt, bestimmte Fragen mit einem Satz beantworten zu können. Und Zurückhaltung mit flames wie "dämlich", "Langeweile" etc. kann auch nich schaden. Miverständnisse lassen sich nicht immer ausschließen, aber wenn alle angemessen versuchen, sie zu vermeiden, spart man sich viel Ärger


----------



## byte (27. Nov 2008)

"Lokomotive von JComponent ableiten" <-- wie man daraus eine Grundsatzdiskussion über MVC vom Zaun brechen kann in einem Thread, wo überhaupt keiner nach MVC gefragt hat, sondern wo es lediglich ums Zeichnen einer Lokomotive geht, ist mir echt schleierhaft.
Aber sorry, dass ich einfach nur die Frage beantwortet habe, ohne unter in Anspruchnahme meiner hellseherischen Fähigkeiten in einem Rundumschlag alle möglichen Mißverständnisse eines potentiellen Java Anfängers bezüglich MVC aus dem Weg zu räumen. :roll: 
Im Gegensatz zu manch anderem hier muss ich nebenbei nämlich auch noch Arbeiten, übrigens in Java.


----------



## André Uhres (27. Nov 2008)

Daß wir JComponent nicht als Modell, sondern als View nehmen, 
war wohl den meisten bereits nach dem Post von SlaterB klar:
http://www.java-forum.org/de/viewtopic.php?p=469410#469410

Ich glaube noch immer, daß die ursprüngliche Fragestellung mehr in Richtung Malen der View geht.
Das Swing Malsystem liefert einen geeigneten Rahmen, um auf einer graphischen Benutzerschnittstelle 
die richtigen Bits zur richtigen Zeit darzustellen. Leider werden die APIs, die ihn verwirklichen, 
von manchen Entwicklern nicht gut verstanden. Wir können aber bei Sun (und anderen) 
gute Tutorials und Artikel finden, die uns weiterhelfen können.


----------



## Marco13 (27. Nov 2008)

Manchmal sind so scheinbar spitzfindige Unterscheidungen wie zwischen "Zeichnen einer Lokomotive" und "Aus einer Lokomotive etwas machen, was unter anderem gezeichnet werden kann" schon angebracht. Ich habe nämlich die Erfahrung gemacht, dass unpräzise Aussagen schon unter "Experten" beliebig hohes Konflikt- und Mißverständnispotential bergen. Und WENN ich in einem Thread antworte, versuche ich darum (auch wenn ich i.a. hauptsächlich abends oder in der Mittagspause antworte) gute, richtige und angemessen ausführliche Antworten zu geben - und antworte nicht, wenn ich dazu nicht die Möglichkeit sehe. 
Wie auch immer. Das hat sich ja jetzt geklärt - hätte nur nicht so lange dauern müssen.


----------



## André Uhres (27. Nov 2008)

@Adam: wenn du noch Fragen hast, nur zu. Unser "Streit" ist ja jetzt abgehakt :wink:


----------

