You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaFX中KeyFrame与Timeline动画方法线性执行的实现问题

问题根源

你之前的代码里,Timeline设置了Timeline.INDEFINITE无限循环,这种情况下setOnFinished回调永远不会被触发——因为动画永远不会自然结束,所以a2的动画根本没机会启动。

解决方案

要实现a1动画完成后再启动a2,核心是让a1的动画有明确的结束时机,然后通过setOnFinished监听结束事件,再启动a2。下面分两种场景给出代码:

场景1:动画是有限次数循环

如果你的动画不需要无限循环,直接设置固定的循环次数,然后让animation方法返回Timeline,方便外部监听结束事件:

修改后的Example类

public class Example{

    // 返回Timeline,让外部可以监听结束事件
    public Timeline animation(){
        Timeline timeline = new Timeline();
        KeyFrame keyFrame = new KeyFrame(Duration.millis(10), event -> {
            // 这里写你的动画逻辑
        });

        timeline.getKeyFrames().add(keyFrame);
        // 设置动画循环次数,比如50次(替换成你需要的次数)
        timeline.setCycleCount(50); 
        timeline.play();
        return timeline;
    }
}

调用代码

@Override
public void start(Stage primaryStage) throws IOException{
    Example a1 = new Example();
    Example a2 = new Example();

    Timeline a1Timeline = a1.animation();
    // 监听a1动画结束,触发后启动a2
    a1Timeline.setOnFinished(event -> {
        a2.animation();
    });
}

场景2:动画需要无限循环,手动控制结束时机

如果必须用无限循环,需要给Example类添加停止动画的方法,在合适的时机停止a1的动画,触发setOnFinished后再启动a2:

修改后的Example类

public class Example{
    private Timeline timeline;

    public void animation(){
        timeline = new Timeline();
        KeyFrame keyFrame = new KeyFrame(Duration.millis(10), event -> {
            // 这里写你的动画逻辑
        });

        timeline.getKeyFrames().add(keyFrame);
        timeline.setCycleCount(Timeline.INDEFINITE);
        timeline.play();
    }

    // 手动停止动画的方法
    public void stopAnimation(){
        if(timeline != null && timeline.getStatus() == Animation.Status.RUNNING){
            timeline.stop();
        }
    }

    // 获取Timeline,方便外部监听结束事件
    public Timeline getTimeline(){
        return timeline;
    }
}

调用代码(以3秒后停止a1为例)

@Override
public void start(Stage primaryStage) throws IOException{
    Example a1 = new Example();
    Example a2 = new Example();

    a1.animation();
    // 用一个临时Timeline控制停止时机,比如3秒后停止a1
    Timeline stopTrigger = new Timeline(new KeyFrame(Duration.seconds(3), event -> {
        a1.stopAnimation();
        // 监听a1结束,启动a2
        a1.getTimeline().setOnFinished(finishEvent -> {
            a2.animation();
        });
    }));
    stopTrigger.play();
}

补充说明

如果你的动画结束条件是基于业务逻辑(比如某个变量达到阈值),可以在KeyFrame的事件回调里判断条件,满足时直接调用timeline.stop(),这样也会触发setOnFinished:

KeyFrame keyFrame = new KeyFrame(Duration.millis(10), event -> {
    // 业务逻辑判断
    if(/* 满足结束条件 */){
        timeline.stop();
    }
});

内容的提问来源于stack exchange,提问作者GreatField

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 03:01:02