12.10Animationen
Grafische Programme müssen sich in AWT oder Swing selbst um Animationen kümmern, etwa indem sie einen Timer-Thread starten und dann ein Neuzeichnen (Repaint) motivieren. In der Zeichenroutine müssen sich die Komponenten dann selbst bewegen, ausblenden – oder was auch immer die Animation fordert.
JavaFX bringt Animationsunterstützung mit und unterstützt Entwickler in dem Trend, dass moderne grafische Oberflächen heutzutage nicht einfach Komponenten irgendwo hinsetzen oder sie verschwinden lassen, sondern den Betrachter subtil über Veränderungen informieren.
Bei Animationen werden Eigenschaften wie Farbe, Transparenz oder Position verändert. Ein zentraler Unterschied ist nur, ob eine Animation etwa eine Bewegung automatisch vornimmt oder ob wir selbst die Koordinaten für eine Bewegung von Hand setzen. Daher unterscheidet JavaFX zwei Typen von Animationen:
Übergangsanimationen (Transitions): Dazu zählen automatische Animationen, wie das Ausblenden, die Skalierung oder die Bewegung entlang eines Pfades. Es ist lediglich der Start- und Endzustand anzugeben, und den Rest regelt JavaFX automatisch. Die Transitionen können auch kombiniert werden, etwa sequenziell hintereinander oder parallel gepaart werden.
Zeitleistenanimationen (Timeline): Bei den Transitions geschieht innerhalb einer gewissen Zeit eine Animation, aber es ist nicht offensichtlich, bei welchem Zeitpunkt welche Koordinate oder welcher Zustand modifiziert wird. Das ist bei den Timeline-Animationen anders. Hier stehen die Zeitpunkte im Mittelpunkt, an denen etwas passiert. Innerhalb dieser Zeitleiste arbeitet das System Key-Frames ab. Zwischen dem Start-Key-Frame und dem End-Key-Frame können wir Properties verändern (den KeyValue setzen) oder uns Ticks, also Events, generieren lassen, an denen wir selbst individuell Eigenschaften ändern können.
12.10.1FadeTransition
Zum Ausblenden von Knoten dient die FadeTransition. Die zentralen Parameter sind Dauer, Starttransparenz, Endtransparenz oder das Ein-/Ausblenden, das zyklisch ist. Das nächste Beispiel zeigt, wie der Klick auf die Schaltfläche diese verschwinden lässt:
Listing 12.17com/tutego/insel/javafx/FadeTransitionDemo.java, start()
public void start( Stage stage ) {
final Button b = new Button( "Klick mich" );
b.setOnAction( new EventHandler<ActionEvent>() {
@Override public void handle( ActionEvent e ) {
FadeTransition t = new FadeTransition( Duration.seconds( 0.5 ), b );
t.setFromValue( 1.0f );
t.setToValue( 0.0f );
t.play();
}
} );
stage.setScene( new Scene( new Group( b ) ) );
stage.show();
}
Die Vorbelegung der From/To-Werte ist 1, sodass setFromValue(1.0f) unnötig ist.
Wer einen Effekt mit »aus- und dann wieder einblenden« wünscht, also von Animation A1 auf eine A2 gehen möchte und zurück, also A1 R A2 R A1, der kann die Zeilen
t.setAutoReverse( true );
mit aufnehmen. Dann gibt es zwei Animationen, bei denen nach dem ersten Ablauf JavaFX die zweite Animation von hinten nach vorne abspielt. Soll endlos animiert werden, ist ein Aufruf von setCycleCount(Timeline.INDEFINITE) möglich.
12.10.2ScaleTransition
Die ScaleTransition skaliert ein Objekt in der x/y-Achse. Werte kleiner 1 lassen es schrumpfen, und Werte größer 1 blasen es auf. Unser nächstes Beispiel zeigt, wie eine Schaltfläche innerhalb von 2 Sekunden auf das Doppelte in der Horizontalen und gegen null auf der Vertikalen skaliert wird:
Listing 12.18com/tutego/insel/javafx/ScaleTransitionDemo.java, start()
public void start( Stage stage ) {
final Button button = new Button( "Klick mich" );
button.setOnAction( new EventHandler<ActionEvent>() {
@Override public void handle( ActionEvent e ) {
ScaleTransition t = new ScaleTransition( Duration.seconds( 2 ), button );
t.setFromX( 1 );
t.setFromY( 1 );
t.setToX( 2 );
t.setToY( 0 );
t.play();
}
} );
stage.setScene( new Scene( new VBox( new Label("Vor"), button, new Label("Nach") ) ) );
stage.show();
}
Standardmäßig stehen auch hier die Werte auf 1, sodass wir uns setFromX(1) und setFromY(1) hätten sparen können.
12.10.3Transitionen parallel oder sequenziell durchführen
Transitionen lassen sich zu Folgen verbinden, wobei zu unterscheiden ist, ob JavaFX die Transitionen parallel oder sequenziell abarbeitet. Dazu wird ein Objekt vom Typ ParallelTransition oder SequentialTransition aufgebaut, und dem Container werden dann Transitionen als Kinder zugewiesen.
Unser nächstes Beispiel blendet die Schaltfläche aus und lässt gleichzeitig die y-Achse auf 0 schrumpfen:
Listing 12.19com/tutego/insel/javafx/ParallelTransitionDemo.java, start()
public void start( Stage stage ) {
final Button b = new Button( "Klick mich" );
b.setOnAction( new EventHandler<ActionEvent>() {
@Override public void handle( ActionEvent e ) {
ScaleTransition t1 = new ScaleTransition( Duration.seconds( 2 ), b );
t1.setToY( 0 );
FadeTransition t2 = new FadeTransition( Duration.seconds( 2 ), b );
t2.setToValue( 0.0f );
ParallelTransition parallelTransition = new ParallelTransition();
parallelTransition.getChildren().addAll( t1, t2 );
parallelTransition.play();
}
} );
stage.setScene( new Scene( b ) );
stage.show();
}