延迟功能无法正常工作?

时间:2016-06-28 13:10:13

标签: java for-loop javafx delay timeline

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

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

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

Screenshot of the implementation of the delay section

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

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

那么如何使延迟按预期工作?据我所知,Timeline是实现延迟的最佳方法之一,而不是可靠的Thread.sleep方法,它会在您执行代码时大大降低设备速度。

作为参考,第一,第二,第三,第四和第五是按钮的名称。 storebutton函数存储当前按钮的位置,供以后在游戏中引用(你可以忽略那个句子,它不会影响延迟的执行),borderglow是按钮发光效果,而generator是Random类中的对象它生成0到5之间的随机整数。

请花点时间考虑这个问题,这是令人费解的,我无法解决这个问题。在IDE中尝试这个想法,甚至更好地理解问题。任何帮助将不胜感激。我提前感谢:)

2 个答案:

答案 0 :(得分:1)

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);

答案 1 :(得分:0)

调用Timeline#play会运行Timeline,但会立即返回。您实际上是在创建多个单独的时间轴,并且几乎同时运行它们。

为了达到预期效果,您可以选择以下几种方法:

  1. 创建一个时间轴,向其中添加KeyFrame,每个时间轴都有相应更高的时间目标:

    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();
    
  2. 这将创建一个TimelineKeyFrame的目标时间为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();