如何在JavaFX中逐个播放StrokeTransition类型ArrayList的动画?
实现JavaFX线条动画逐个依次播放的方案
我明白你想要的效果:让trans列表里的每个StrokeTransition动画按顺序逐个播放,完成一个线条的颜色过渡后,再启动下一个。你的现有代码已经正确创建了线条和对应的动画,但缺少按顺序触发动画的逻辑,默认直接启动所有动画会导致它们同时播放。下面给你两种简单的解决方法:
方法1:用SequentialTransition(推荐,代码更简洁)
JavaFX提供了SequentialTransition类,专门用来按顺序执行多个动画,非常适合你的场景。在你现有代码的末尾添加以下代码即可:
// 创建序列动画容器,用来按顺序执行所有线条动画 SequentialTransition sequentialAnim = new SequentialTransition(); // 将trans列表中的所有动画添加到序列中 sequentialAnim.getChildren().addAll(trans); // 启动整个序列动画 sequentialAnim.play(); // 可选:如果需要循环播放整个序列,可以添加这行 // sequentialAnim.setCycleCount(Animation.INDEFINITE);
为什么好用?
- 不需要手动处理动画的结束回调,JavaFX会自动管理顺序
- 支持暂停、继续、重置等操作,方便控制整个动画流程
- 动画顺序完全遵循
trans列表中元素的添加顺序,和你创建线条的顺序一致
方法2:手动通过setOnFinished链式触发
如果你不想用容器类,也可以手动给每个动画设置结束回调,让前一个动画完成后自动启动下一个:
// 确保trans列表不为空再执行 if (!trans.isEmpty()) { // 给每个动画(除了最后一个)设置结束回调 for (int i = 0; i < trans.size() - 1; i++) { int currentIndex = i; trans.get(i).setOnFinished(event -> { // 当前动画结束后,启动下一个动画 trans.get(currentIndex + 1).play(); }); } // 手动启动第一个动画,开启整个链式流程 trans.get(0).play(); }
注意事项
- 动画顺序:确保
trans列表中的动画顺序和你想要播放的线条顺序一致,因为序列是严格按照列表顺序执行的 - 时长调整:你当前设置的动画时长是10秒(
Duration.millis(10000)),如果觉得太长可以修改这个数值,比如改成2秒就是Duration.millis(2000) - 线条样式:如果需要在动画结束后保持最终颜色(蓝色),你的
StrokeTransition已经设置了从CYAN到BLUE的过渡,结束后会自动保留BLUE,不需要额外处理
整理后的完整代码参考
import javafx.animation.Animation; import javafx.animation.SequentialTransition; import javafx.animation.StrokeTransition; import javafx.scene.paint.Color; import javafx.scene.shape.Line; import javafx.util.Duration; import java.util.ArrayList; // ... 你的其他代码 ... int a = 0; ArrayList<Line> nodeline = new ArrayList<Line>(); ArrayList<StrokeTransition> trans = new ArrayList<StrokeTransition>(); ArrayList<Double> lineaxisx = new ArrayList<Double>(); ArrayList<Double> lineaxisy = new ArrayList<Double>(); for(int i = 0; i < dainput.size(); i += 3) { lineaxisx.add((double)axisx.get(dainput.get(i))); lineaxisx.add((double)axisx.get(dainput.get(i+1))); lineaxisy.add((double)axisy.get(dainput.get(i))); lineaxisy.add((double)axisy.get(dainput.get(i+1))); nodeline.add(new Line( axisx.get(dainput.get(i)), axisy.get(dainput.get(i)), axisx.get(dainput.get(i+1)), axisy.get(dainput.get(i+1)) )); nodeline.get(a).setStroke(Color.CYAN); for(int j = 0; j < daiout.size(); j += 3){ if(daiout.get(j) == dainput.get(i) && daiout.get(j+1) == dainput.get(i + 1) && daiout.get(j + 2) == dainput.get(i + 2)){ trans.add(new StrokeTransition( Duration.millis(10000), nodeline.get(a), Color.CYAN, Color.BLUE )); } } root.getChildren().addAll(nodeline.get(a)); a++; } // 这里添加顺序播放的逻辑(二选一即可) // 方法1:SequentialTransition SequentialTransition sequentialAnim = new SequentialTransition(); sequentialAnim.getChildren().addAll(trans); sequentialAnim.play(); // 方法2:手动链式触发(注释掉方法1后启用) /* if (!trans.isEmpty()) { for (int i = 0; i < trans.size() - 1; i++) { int currentIndex = i; trans.get(i).setOnFinished(event -> { trans.get(currentIndex + 1).play(); }); } trans.get(0).play(); } */
内容的提问来源于stack exchange,提问作者Hawk3
相关产品推荐
相关产品推荐

