延迟功能不能正常工作?

Delay function does not work properly?

我是这个社区的新手,我有一个问题我自己似乎无法解决,甚至在搜索 google 并向朋友寻求答案时也是如此。

我正在制作一个小模式记忆游戏,它围绕着按特定顺序单击按钮,每次成功都会变得更难,直到失败为止。通过 javafx GUI 进行设置,IDE 是 NetBeans 8.1。

现在,例如,当一个序列通过按钮发光显示给玩家时,每个按钮和序列中的下一个按钮之间需要有一个延迟,以便玩家知道他们的顺序d 单击按钮。 我尝试了三个延迟函数,但都产生了相同的结果,它们是 Thread.sleep 、时间轴和过渡。

如您在上图中所见,此 for 循环随机选择游戏中 5 个按钮之一,并使其发光,以便玩家知道这是序列中的下一个按钮。所有这些都发生在循环的每次迭代中创建的新时间轴内,因此每次选择和显示按钮时都会发生延迟。

但是,当我执行这部分代码时,我看到的很奇怪。 for 循环存在于按钮事件处理程序中。当我单击此按钮时,我确实看到了延迟,但不是在每个按钮和序列中的下一个按钮之间,而是在单击按钮和立即显示整个序列之间存在延迟。

那么如何让这个延迟按预期工作呢?据我所知,时间线是实现延迟的最佳方法之一,与不可靠的 Thread.sleep 方法相反,后者在执行代码时会大大降低设备速度。

作为参考,第一、第二、第三、第四和第五是按钮的名称。 storebutton函数存储当前按钮的位置,供以后在游戏中参考(那句话可以忽略,不影响延时的实现),borderglow是按钮发光效果,generator是从Randomclass 生成一个介于 0 和 5 之间的随机整数。

请您慢慢考虑这个问题,这很令人费解,我无法解决这个问题。在你的 IDE 中尝试这个想法,甚至可以更好地理解问题。任何帮助将不胜感激。提前致谢:)

正在调用 Timeline#play 运行 Timeline,但立即 returns。您实际上是在创建多个单独的时间线,并且几乎同时 运行 将它们全部连接起来。

要达到预期效果,您有以下几种选择:

  1. 创建一个单独的时间线,向其中添加 KeyFrames,每个时间线依次增加:

    Timeline timeline = new Timeline();
    for (int i=0; i<buttoncount; i++) {
        timeline.getKeyFrames().add(new KeyFrame(Duration.millis((i+1)*1000), e -> {
            // Change highlighted button
        });
    } 
    timeline.play();
    

这将创建一个 Timeline,目标时间为 KeyFrames 1000、2000、3000 ... 毫秒。

  1. 创建一个时间轴,其中包含单个 KeyFrame 固定时间,并 运行 多次:

    Timeline timeline = new Timeline(new KeyFrame(Duration.millis(1000), e -> {
        // This will be called multiple times, each time reset the highlighted button and select a new one to highlight
    }));
    timeline.setCycleCount(buttoncount);
    timeline.play();
    

A PauseTransition 可用于此目的。您可以使用 onFinished 事件处理程序来更新 UI 并在必要时重播转换:

List<Button> buttons = ...

// list of glowing indices
List<Integer> indices = Arrays.asList(0, 3, 2, 1, 3, 1);

PauseTransition transition = new PauseTransition(Duration.seconds(1));

EventHandler<ActionEvent> handler = new EventHandler<ActionEvent>() {

    private int currentIndex = 0;
    private final Iterator<Integer> iterator = indices.iterator();
    private final Effect effect = new Glow(200);

    @Override
    public void handle(ActionEvent event) {
        buttons.get(currentIndex).setEffect(null);
        if (iterator.hasNext()) {
            currentIndex  = iterator.next();
            buttons.get(currentIndex).setEffect(effect);
            transition.play();
        }
    }

};

transition.setOnFinished(handler);

// activate first button & start animation
handler.handle(null);