In Java ist es möglich, Animationen darzustellen.
Man kann dies auf drei Arten realisieren:
- Indem man die Position der zu zeichnenden Objekte schrittweise verändert.
- Indem man eine Folge von Einzelbildern nacheinander in der richtigen Reihenfolge an dieselbe Stelle malt.
- Indem man über ein Exemplar
von MemoryImageSource oder
BufferedImage ein Bild aus rohen Pixeldaten erstellt.
In diesem Abschnitt wird nur auf die ersten beiden Techniken eingegangen. Mehr über die dritte
Technik kann dem Abschnitt 12.8 entnommen werden.
Bei allen drei Methoden muss die Komponente in regelmäßigen Abständen neu gezeichnet werden,
nämlich immer dann, wenn die dargestellte Grafik aktualisiert werden soll.
Hierzu besitzt jede Komponente die Methode repaint(). Durch Aufruf von repaint()
wird die Komponente jedoch nur aufgefordert, sich neu zu zeichnen.
Es ist nicht sicher, ob das
auch geschieht, denn es hängt davon ab, inwieweit die Applikations-Threads die CPU abgeben. Erst dann kann das AWT die Komponenten neu zeichnen.
Der Zeichenvorgang wird jeweils zum nächstmöglichen Zeitpunkt
stattfinden, und dessen Ausführung ist asynchron zum Aufruf.
Man kann repaint() aber auch eine Zeit in Millisekunden
übergeben, die angibt, wann die Komponente neu gezeichnet werden soll:
repaint(100);
fordert die Komponente auf, sich frühestens nach 100 Millisekunden neu
zu zeichnen. Diese Art des Aufrufs bietet
aber auch keine Garantie dafür, dass die Komponente
neu gezeichnet wird. Wird repaint() ohne Parameter aufgerufen, beträgt
die eingestellte Wartezeit 0 Millisekunden.
Eine andere Möglichkeit, eine Komponente neu zu zeichnen, besteht im
direkten Aufruf der paint()-Methode:
paint(getGraphics());
paint() erwartet als einzigen Parameter das Graphics-Objekt,
das die Zeichenfläche repräsentiert, in die gezeichnet werden soll. Das Graphics-Objekt einer
Komponente kann durch Aufruf der Methode getGraphics() erfragt werden.
Ruft man nun paint() mit diesem Graphics-Objekt als
Argument auf, so erreicht man, dass die Komponente neu gezeichnet wird.
Im Unterschied zu repaint() ist aber zu beachten, dass bei einem direkten Aufruf von paint() der Zeichenvorgang in jedem Fall ausgeführt
wird und synchron erfolgt,
d. h. ein Aufruf von paint() kehrt erst dann wieder zurück, wenn alle
Zeichenoperationen ausgeführt wurden. Bei einem Aufruf von repaint()
hingegen wird der Zeichenvorgang einem anderen Thread übertragen. Dadurch kehrt
repaint() nach einem Aufruf sofort wieder zurück, und der
eigentliche Zeichenvorgang wird später oder überhaupt nicht ausgeführt, je
nach Auslastung.
Es ist vor allen Dingen dann wichtig, einen synchronen Zeichenvorgang
zu verwenden, wenn kein Bild in der Animation »verlorengehen« darf.
Das wäre der Fall, wenn man eine Ampel implementiert, die den Startvorgang
einer Anwendung anzeigt. Nach der Aufforderung, das Programm zu starten, wechselt
die Ampel ihre Farbe von Rot auf Gelb. Nach Abschluss des Startvorgangs erfolgt wiederum
ein Wechsel von Gelb nach Grün. Würde nach der Aufforderung zum Start die Ampel nicht auf Gelb
wechseln, so würde der gewünschte Effekt u. U. nicht eintreten.
Da bei einer Animation
mehrere Zeichenaufforderungen nacheinander vorliegen, wird
der Aufruf in einer Schleife vorgenommen.
Die Darstellung einer Animation kann im Allgemeinen in folgende Schritte zerlegt werden:
- Verändern von globalen Parametern, die den augenblicklichen Zustand der
Animation beschreiben
- Aufruf von repaint(), hierdurch wird die Komponente neu gezeichnet und
somit aktualisiert.
Werden obige Anweisungen in einer Schleife ausgeführt, ist ein kompletter
Bewegungsablauf definiert, der durch den eingebauten Aufruf von repaint()
auf dem Bildschirm dargestellt wird.
Meist wird eine Animation in einem eigenen Thread ausgeführt.
Wie man dies genau macht, wird in folgenden Abschnitten am Beispiel
einer Laufschrift bzw. eines Videoplayers
erklärt.
Copyright © 2002 dpunkt.Verlag, Heidelberg. Alle Rechte vorbehalten.