【问题标题】:Playing multiple timeline animation in order按顺序播放多个时间线动画
【发布时间】:2019-07-24 19:27:08
【问题描述】:

我正在尝试通过列表播放搜索,如果该列表包含key 字,它将播放该动画。

如果 myList 包含{"Cloudy","Cloudy,"Cloudy","Clear"} 它应该播放 cloudyT 动画并循环 3 次然后 clearT 动画。但 那不是演员表。我注意到它同时执行所有 4 个动画,导致只显示一个动画。我的 setCycleCount 对所有这些都是相同的。

我还注意到 print 语句会在动画完成之前一次性打印所有内容,这意味着它不会等待动画完成。

for (int i = 0; i < time.length;i++) {  
    if (myList.get(i).equals("Cloudy")) {
        System.out.println("Cloudy found");
        cloudyGrp.setVisible(true); //Group
        cloudyT.setRate(.5); //Timeline
        cloudyT.play();
        cloudyT.setOnFinished(event -> {
            cloudyGrp.setVisible(false);
            System.out.println("Cloudy animation done");
        });
    }
    if (myList.get(i).equals("Clear")) {
        clearGrp.setVisible(true); //Group
        clearT.setRate(.5); 
        clearT.play(); //Timeline
        clearT.setOnFinished(event -> {
            clearGrp.setVisible(false);
            System.out.println("Clear animation done");
        });
    }
    //other if statement with same layout

如何将它们分开,以便它们一个接一个地单独播放?

我想过使用Threads 并使用优先级,但不知道如何实现它。谢谢。

【问题讨论】:

  • 我想你在找else if
  • @VinceEmigh 可悲的是 else if 仍然给出同样的错误
  • 我的错,我看错了代码。看来您需要使用回调系统setOnFinished,因为循环的迭代速度比动画播放的速度要快。而不是循环,也许你可以递归地处理这个。我会在大约 10 分钟后检查一下,正要回家。
  • 如果我的答案看起来太复杂,请告诉我,我会简化的。
  • @VinceEmigh 谢谢你这么详细的解释,我会在课后几个小时试试

标签: java animation timeline


【解决方案1】:

问题

您的循环迭代速度快于动画播放速度。

使用递归代替循环,利用setOnFinished 触发数组中的下一个动画。


解决方案

引入新类型

当动画开始时,组应该是可见的。当动画停止时,该组应该被隐藏。

新类型会将动画与其可显示组分组:

class AnimationWrapper {
    private Animation animation;
    private Group group;

    public AnimationWrapper(Animation animation, Group group) {
        this.animation = animation;
        this.group = group;
    }
}

这种新类型将通过一些play 方法处理动画的播放以及组的隐藏/显示。

AnimationWrapper#play 方法将接受动画结束时的回调函数。

class AnimationWrapper {
    // ...

    public void play(Runnable onFinished) {
        group.setVisible(true);
        animation.setOnFinished(e -> {
            group.setVisible(false);
            onFinished.run();
        });

        animation.setRate(.5);
        animation.play();
    }
}

String 值映射到其受尊重的AnimationWrapper

最终目标是引入一个简单的界面:“根据String 数组中的值播放动画。

原来有循环的类会引入一个Map 字段:

Map<String, AnimationWrapper> animations = new HashMap<>();

// populate somewhere
animations.put("Cloudy", new AnimationWrapper(cloudyT, cloudyGroup);

在处理String[]的请求时,Map可以让你轻松抓取动画。

使用递归

目标是执行:

play > onFinished > play > onFinished > ...`

这种模式应该一直持续到您用尽了请求数组中的所有 String 值。

在带有Map 的类中,我们将声明一个play(String[]),它将处理从数组请求的动画的播放。

void play(String[] items) {
    play(items, 0);
}

void play(String[] items, int index) {
     // TODO
}

引入重载将使我们能够跨方法调用跟踪索引。

在重载方法中,首先检查是否为index &gt;= items.length。如果索引超过数组的长度,则返回/退出。

void play(String[] items, int index) {
    if(index >= items.length)
        return;
}

如果索引不超过,我们将使用它来获取请求的动画,并使用请求从Map 访问动画包装器:

void play(String[] items, int index) {
    if(index >= items.length)
        return;

    String requestedAnim = items[index];
    AnimationWrapper anim = animations.get(requestedAnim);
}

一旦你有了动画,就播放它。完成后,使用下一个索引调用play

void play(String[] items, int index) {
    if(index >= items.length)
        return;

    String requestedAnim = items[index];
    AnimationWrapper anim = animations.get(requestedAnim);
    anim.play(() -> play(items, index + 1));
}

原来有循环的地方,现在可以调用:

String[] requests = { "Cloudy", "Cloudy", "Cloudy", "Clear" };
play(requests);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-15
    相关资源
    最近更新 更多