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
相关产品推荐
相关产品推荐

