如何在 JavaFX 中延迟 10 秒在 TextArea 中附加文本?

Posted

技术标签:

【中文标题】如何在 JavaFX 中延迟 10 秒在 TextArea 中附加文本?【英文标题】:How to append text in a TextArea by delay of 10 seconds in JavaFX? 【发布时间】: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上延迟每次迭代 【参考方案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 设为线程安全集合(如ConcurrentLinkedDeque 或CopyOnWriteArrayList),或者自己实现线程安全,这可能比您预期的代码更复杂.

【讨论】:

【参考方案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);

【讨论】:

在应用程序线程中休眠会阻止应用程序更新和接收用户输入。

以上是关于如何在 JavaFX 中延迟 10 秒在 TextArea 中附加文本?的主要内容,如果未能解决你的问题,请参考以下文章

如何每 10 秒在前台和后台更新用户位置? [复制]

在 JavaFX 中管理 ComboBox 项

如何每 5 秒在值之间切换 TextView

如何在 setText 之后滚动 JavaFX TextArea

JavaFX延迟for循环中的颜色变化

JavaFX:循环之间的旋转动画延迟