【问题标题】:How to append text in a TextArea by delay of 10 seconds in JavaFX?如何在 JavaFX 中延迟 10 秒在 TextArea 中附加文本?
【发布时间】:2019-06-07 05:21:41
【问题描述】:

我有这个将数据粘贴到TextArea 的函数,我想在DisplayChain 的每次迭代中附加文本,10 秒后(只是一个示例)。我应该使用什么?

这是我的DisplayChain 代码:

public void DisplayChain() {    
    for(int i=0;i<chain.size();i++) {
        a.appendText("Block: " + i + "\n");
        a.appendText("Version: " + chain.get(i).getVersion()+ "\n");
        a.appendText("TimeStamp: " + chain.get(i).getTimestamp()+ "\n");
        a.appendText("PreviousHash: " + chain.get(i).getPreviousHash()+ "\n");
        a.appendText("Hash: " + chain.get(i).getHash()+ "\n");
        a.appendText("\n"); 
    }
}

【问题讨论】:

  • 您是否正在处理DisplayChain 方法中的迭代?
  • @thepooran 是的,我想在DisplayChain上延迟每次迭代

标签: java user-interface javafx textarea


【解决方案1】:

最简单的方法是使用 Thread.sleep 方法,但不能在 JavaFX 应用程序线程中调用它。如果你这样做,你会阻塞应用程序本身:在你的睡眠调用完成之前,不会呈现控件并且不会响应来自鼠标或键盘的用户输入。

这意味着不能从事件处理程序或侦听器调用 Thread.sleep。要解决这个问题,请从一个全新的线程调用 Thread.sleep。

然而,虽然 Thread.sleep 不能在应用程序线程中调用,但 JavaFX 方法的情况正好相反:它们必须从应用程序线程中调用。 Platform.runLater 方法允许您这样做:

Runnable task = () -> {
    try {
        for (int i = 0; i < chain.size(); i++) {
            int index = i;
            Platform.runLater(() -> {
                a.appendText("Block: " + index + "\n");
                a.appendText("Version: " + chain.get(index).getVersion()+ "\n");
                a.appendText("TimeStamp: " + chain.get(index).getTimestamp()+ "\n");
                a.appendText("PreviousHash: " + chain.get(index).getPreviousHash()+ "\n");
                a.appendText("Hash: " + chain.get(index).getHash()+ "\n");
                a.appendText("\n"); 
            });

            Thread.sleep(10000);
        }
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
};
new Thread(task).start();

int index = i; 的原因是局部变量不能被其他类读取,例如提供给 Platform.runLater 的匿名 Runnable,除非它们是最终的(或实际上是最终的)。

上面的代码假设chain 集合没有改变。如果在您阅读它时它可能会发生变化,您必须将chain 设为线程安全集合(如ConcurrentLinkedDequeCopyOnWriteArrayList),或者自己实现线程安全,这可能比您预期的代码更复杂.

【讨论】:

    【解决方案2】:

    使用Timeline 重复触发appendText 调用以进行单个“循环迭代”:

    final Timeline timeline = Timeline();
    
    EventHandler<ActionEvent> handler = new EventHandler<ActionEvent>() {
    
        int i = 0;
    
        @Override
        public void handle(ActionEvent e) {
            if (i >= chain.size()) {
                // stop thread, if index exceeds chain size
                timeline.stop();
            } else {
                // execute a single "loop iteration"
                a.appendText("Block: " + i + "\n"
                             + "Version: " + chain.get(i).getVersion()+ "\n"
                             + "TimeStamp: " + chain.get(i).getTimestamp()+ "\n"
                             + "PreviousHash: " + chain.get(i).getPreviousHash()+ "\n"
                             + "Hash: " + chain.get(i).getHash()+ "\n"
                             + "\n");
                i++;
            }
        }
    
    };
    timeline.getKeyFrames().add(new KeyFrame(Duration.seconds(10), handler));
    timeline.setCycleCount(Animation.INDEFINITE); // keep timeline running until handler stops it
    timeline.play();
    

    注意:我建议将chain.get(i) 提取到一个局部变量中,以避免多次访问该集合。

    【讨论】:

      【解决方案3】:

      你可以申请javafx.application.Platform:

      new Thread ( () -> {
          try {
              Thread.sleep ( delayMs ); // 1000 in this case
              Platform.runLater ( () -> {
                  ...
              } );
          } catch ( InterruptedException ie ) { }
      } ).start ( );
      

      【讨论】:

        【解决方案4】:

        如果我理解得很好,你可以添加这一行

        Thread.sleep(10000);
        

        【讨论】:

        • 在应用程序线程中休眠会阻止应用程序更新和接收用户输入。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-03-20
        • 1970-01-01
        • 2016-08-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多