Compound Transitions
Along with the basic transition classes presented earlier, javafx.animation.transition provides two classes for grouping transitions: ParallelTransition and SequentialTransition. Each class offers a content variable (of type Transition[]) that stores a sequence of transitions. ParallelTransition plays these transitions in parallel; SequentialTransition plays them in sequence.
There are a couple of items to keep in mind when working with these compound transition classes:
- Each Transition in the content sequence that doesn't specify a value for its node variable inherits the value of its compound transition's node variable.
- Transition's autoReverse, duration, and repeatCount members have no effect on a compound transition.
To demonstrate these compound transition classes, I've created an application that generates a scene consisting of a circle overlaid by text. I've also created transitions for fading the text and circle, and for scaling the circle. A sequential transition first fades out the text and then runs a parallel transition that fades out/in and scales up/down the circle a couple of times. Listing 7 presents the application's source code.
Listing 7Main.fx (from a PSTDemo project).
/* * Main.fx */ package pstdemo; import javafx.animation.transition.FadeTransition; import javafx.animation.transition.ParallelTransition; import javafx.animation.transition.ScaleTransition; import javafx.animation.transition.SequentialTransition; import javafx.scene.Scene; import javafx.scene.paint.Color; import javafx.scene.paint.LinearGradient; import javafx.scene.paint.RadialGradient; import javafx.scene.paint.Stop; import javafx.scene.shape.Circle; import javafx.scene.text.Font; import javafx.scene.text.Text; import javafx.scene.text.TextOrigin; import javafx.stage.Stage; def BACKGROUND_PAINT = LinearGradient { startX: 0.0 startY: 0.0 endX: 0.0 endY: 1.0 stops: [ Stop { offset: 0.0 color: Color.BEIGE } Stop { offset: 1.0 color: Color.CORAL } ] } var circle: Circle; var text: Text; def FADEC_TRANSITION = FadeTransition { node: bind circle fromValue: 1.0 toValue: 0.0 duration: 2s repeatCount: 4 autoReverse: true } def FADETOUT_TRANSITION = FadeTransition { node: bind text fromValue: 1.0 toValue: 0.0 duration: 4s } def FADETIN_TRANSITION = FadeTransition { node: bind text fromValue: 0.0 toValue: 1.0 duration: 4s } def SCALEC_TRANSITION = ScaleTransition { var count = 0 node: bind circle fromX: 1.0 fromY: 1.0 toX: 0.25 toY: 0.25 duration: 2s repeatCount: 4 autoReverse: true action: function (): Void { if (++count == 2) FADETIN_TRANSITION.playFromStart () } } def PAR_TRANSITION = ParallelTransition { content: [ FADEC_TRANSITION, SCALEC_TRANSITION ] } def SEQ_TRANSITION = SequentialTransition { content: [ FADETOUT_TRANSITION, PAR_TRANSITION /*, FADETIN_TRANSITION */ ] } SEQ_TRANSITION.playFromStart (); Stage { title: "PSTransition Demo" width: 250 height: 250 var scene: Scene scene: scene = Scene { fill: BACKGROUND_PAINT content: [ circle = Circle { centerX: bind scene.width/2 centerY: bind scene.height/2 radius: 90 fill: RadialGradient { centerX: 75 centerY: 75 radius: 90 proportional: false stops: [ Stop { offset: 0.0 color: Color.BLUE } Stop { offset: 1.0 color: Color.DARKBLUE } ] } } text = Text { x: bind circle.centerX y: bind circle.centerY translateX: bind -text.layoutBounds.width/2 translateY: bind -text.layoutBounds.height/2 textOrigin: TextOrigin.TOP fill: Color.WHITE font: Font { name: "Arial BOLD" size: 14 } content: "PSTransition Demo" } ] } }
Originally, I placed FADETIN_TRANSITION in SEQ_TRANSITION's content sequence variable, thinking that it would run after PAR_TRANSITION finished. Because I observed FADETIN_TRANSITION running in parallel with PAR_TRANSITION, I commented out this transition and chose a different approach.
Specifically, I decided to take advantage of SCALEC_TRANSITION's action member. This member's function is called twice, at the end of each scale-down cycle (and prior to the scale-up cycle). The function waits for the last scale-down cycle to complete, and then starts the FADETIN_TRANSITION. This results in the text starting to fade in as the circle starts scaling up for the last time.
Figure 7 reveals the scene with the text reverting to full opacity.
Figure 7 The text is at 50% opacity when the circle finishes scaling up.