D-Dᴙum
D-Dᴙum

Reputation: 7890

Add A New KeyFrame to Timeline While an Animation is Executing

I would like to modify a Timeline while it is running, for example in response to a mouse-click I want to change the target value of the animation. I have tried several methods to do this including (in a mouse clicked handler) :

  1. Pausing the animation by calling pause() on the Timeline, clearing the KeyFrames ObservableList, adding a new KeyFrame and calling play() on the Timeline.
  2. Creating a new KeyFrame with a Cue-name, adding the new frame to the Observable list and calling jumpTo(cueName) on the Timeline.

Some example code is:

String cueName = String.valueOf(System.currentTimeMillis());
KeyValue kv = new KeyValue(myObject.rotateProperty(), -90 + 180.0 * Math.random(), new CustomInterpolator());
KeyFrame kf = new KeyFrame(Duration.seconds(10), cueName, kv);
startupTimeline.getKeyFrames().add(kf);
startupTimeline.jumpTo(cueName);
startupTimeline.play();

Neither of these appear to work, the animation just stops.

Should I be able to modify the KeyFrame list of an existing Timeline or do I need to create a new Timeline if I want to change an animation while it is executing?

Upvotes: 0

Views: 1248

Answers (1)

James_D
James_D

Reputation: 209408

To the best of my knowledge, a Timeline can't be changed in that manner once it has started playing. The issue is that you might change the total cycle duration, which would confuse all the interpolation computations.

You probably need an AnimationTimer for this. AnimationTimer has an abstract handle(long timestamp) method which takes a time stamp (in nano-seconds), and is invoked every time the scene graph is rendered. So you can do something like:

AnimationTimer animation = new AnimationTimer() {

    private long startTime = -1;

    @Override
    public void handle(long timestamp) {
        if (startTime == -1) {
            startTime = timestamp ;
        }

        long totalElapsedNanoseconds = timestamp - startTime ;
        // update UI based on elapsed time...
    }
}

The handle() method is invoked on the JavaFX Application Thread, so it is safe to update the UI, and to reference any variables that are only changed on the same thread.

Upvotes: 3

Related Questions