Question

I'm trying to set up some animations to play when my applications switches forms.

I had the code for hiding the form on a Abstract class, implemented by all the forms used on the application.

final synchronized void hide(){
    final Timeline timeline = new Timeline();

    timeline.setCycleCount(1);
    timeline.setAutoReverse(true);

    final KeyValue[] kvArray = new KeyValue[2]; 
    kvArray[0] = new KeyValue(this.getNode().scaleXProperty(), 0);
    kvArray[1] = new KeyValue(this.getNode().scaleYProperty(), 0);
    final KeyFrame kf = new KeyFrame(Duration.millis(500), kvArray);

    timeline.getKeyFrames().add(kf);
    timeline.play();
}

Then a Controller class calls this method, playing the hide animation, and showing the next form. All the forms are displayed in as the center of a border pane, so to switch form I have to switch the node on the center of the used border pane.

The prob is the timeline plays async, so the hide function returns before the animation plays and the new form is shown with no animation.

I've tried unsucessfully to use wait and notify and a onFinished event.

What is the best way to proceed from here?

Was it helpful?

Solution 2

Have you tried to convert the Timeline from a local variable to a field of the class that manages the transtion of your forms and also instantiate it there. Then let hide() only append the KeyFrame to the more global Timeline ...

OTHER TIPS

As hide() is called by FXML it will be run on FX Event Thread and you can't stop and wait on this thread (as this will stop your animation as well).

Easiest solution for this functionality is to provide function which will be called by timeline. E.g.:

final void hide(EventHandler<ActionEvent> nextAction){
    final Timeline timeline = new Timeline();

    timeline.setCycleCount(1);
    timeline.setAutoReverse(true);

    final KeyValue[] kvArray = new KeyValue[2]; 
    kvArray[0] = new KeyValue(this.getNode().scaleXProperty(), 0);
    kvArray[1] = new KeyValue(this.getNode().scaleYProperty(), 0);
    final KeyFrame kf = new KeyFrame(Duration.millis(500), kvArray);

    timeline.getKeyFrames().add(kf);
    // here we call function from parameter
    timeline.setOnFinished(nextAction);
    timeline.play();
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top