JavaFX TextArea 实时更新

5
我正在使用Java FX文本区域,并将其用作提供步骤信息的方式。
步骤如下。 复制文件。 删除旧文件。 复制新文件。 然后从旧文件复制一些属性到新文件中。
整个步骤是在单击按钮时开始的。
我面临的问题是,当我使用附加命令时,文本区域不会立即更新。
附加命令添加数据,当函数终止时,我将所有文本放在一起。 我希望调用函数时文本区域能够更新。
在我的程序中,复制文件操作需要一些时间,因为它是一个大文件。 所以在开始时,我显示消息,表示操作已经开始。 在操作结束时,我想要显示操作已经结束。
但是文本区域会将所有这些文本一起显示。
我在Oracle论坛上读到了,FX中的文本区域使用单个线程,因此在整个过程完成之前不会显示任何内容。
文章:https://community.oracle.com/message/9938117#9938117 有人可以建议我该怎么做吗?
新编辑
好的,在单击按钮时,我调用一个函数来执行以下方法。
  public void executeCmds(){

        createTempDirectory();
        copyConfigPropetiesFileValues();
        copyConfigProperties();
        copyYMLFile();
        copyYMLFileProperties();

        stopTomcatServer();

        deleteOldWar();
        copyNewWar();
        startTomcatServer();

        copyOldConfigFile();
        copyOldYMLFile();
 }

现在每个函数都是一个进程,应该按顺序执行。在每个步骤完成后,我想要更新GUI文本区域,显示成功消息,表示已经完成。
为此,我使用以下方法:
  public void createTempDirectory(){
         //Creating temporary directory for copying property files
         status_text_area.appendText("Trying to create a temp directory \n");
        File tempDir= new       File(tomcat_path.getText()+filePath.path_to_temp_directory);
         if(!tempDir.exists())
             tempDir.mkdirs();

    status_text_area.appendText("Created Temp directory to copy Config Files \n");

}

其他函数也是这样。复制war文件和删除war文件函数需要时间,因为它将130 MB的文件从一个位置复制到另一个位置。

所以我希望文本区域显示为:

  1. 开始复制文件

过一段时间后

  1. 文件已复制

但问题是,文本区域根本不会填充,直到所有函数都执行完毕。

如果我尝试通过线程来执行它们,则无法保证执行顺序。请帮忙解决。


4
JavaFX中的并发开始,例如此处 - trashgod
1
一个相关的例子可以在这里看到:https://dev59.com/GF4c5IYBdhLWcg3wgqr2#27835238。 - trashgod
3个回答

8
在后台线程中运行你的executeCmds()方法,使用Platform.runLater()来更新文本区域:
public void executeCmds(){
    Thread thread = new Thread(() -> {
        createTempDirectory();
        copyConfigPropetiesFileValues();
        copyConfigProperties();
        copyYMLFile();
        copyYMLFileProperties();

        stopTomcatServer();

        deleteOldWar();
        copyNewWar();
        startTomcatServer();

        copyOldConfigFile();
        copyOldYMLFile();
    });
    thread.start();
}

然后

public void createTempDirectory(){
         //Creating temporary directory for copying property files
    updateStatus("Trying to create a temp directory \n");
    File tempDir= new File(tomcat_path.getText()+filePath.path_to_temp_directory);
    if(!tempDir.exists())
        tempDir.mkdirs();

    updateStatus("Created Temp directory to copy Config Files \n");
}

// similarly for other methods

private void updateStatus(String message) {
    if (Platform.isFxApplicationThread()) {
        status_text_area.appendText(message);
    } else {
        Platform.runLater(() -> status_text_area.appendText(message));
    }
}

哇!非常感谢您。 这太完美了,正是我想要的!我也会在那个Oracle论坛上发布您的答案! - Prateek Mishra

0

扩展已批准的响应 - 如果您需要在执行其他操作之前等待更新的UI,请使用PlatformImpl.runAndWait(Runnable runnable)

Thread thread = new Thread(() -> {
    yourMethod();
    PlatformImpl.runAndWait(() -> {
        methodForUI();
    });
    methodAfterUIChanged();
});
thread.start();

-3
请问您能提供一些代码片段吗?
我经常犯同样的错误:concat返回连接字符串,而不修改应用其concat方法的字符串。
        String firstString = "txt";
        String resultString = firstString.concat(" next");

如果您的问题确实与线程有关,并且如果您的代码与文章中提到的代码相似,我建议您通过类似于以下代码的并行线程复制数据: javafx.application.Platform.runLater(e -> { // 在此执行一些长时间操作 }); 请参考有关Task和runlater的现有文章: Platform.runLater and Task in JavaFX

编辑:正如James_D所提到的,如果操作确实很长,最好使用Task。阅读我链接的文章以了解更多关于替代方案及其用法的信息。


1
Platform.runLater(...) 在FX应用程序线程上执行代码。您绝对不应该在FX应用程序线程上执行长时间运行的操作。 - James_D

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接