javafx 文本字段没有改变

我有以下代码:


@FXML

private void test(){

    textField.setText("Pending...");

    boolean passed = doStuff();

    if(passed){

        textField.setText("OK");

    } else {

        textField.setText("Error");

    }

}

我试图实现的是,当 doStuff() 在 GUI 的 textField 中执行他的操作时,应该写成“Pending...”,并且一旦完成,它应该变为“OK”/“Error”。


我希望在 doStuff 运行时阻止 GUI,因此用户必须等待并且不能单击其他内容。


但是发生的情况是,一旦我开始测试,它就会执行 doStuff(),但只会用“OK”/“Error”更新 textField,但我从来没有看到“Pending...”。


我觉得我以某种方式更新了 GUI,但我不确定应该如何完成。


更新: 我尝试将 doStuff 移到另一个线程中:


@FXML

private void test(){

    textField.setText("Pending...");

    Thread t = new Thread(){

        public void run(){

            boolean passed = doStuff();

            if(passed){

                textField.setText("OK");

            } else {

                textField.setText("Error");

            }

        }

    };

    t.start();

    t.join();

}

如果我删除 t.join(); 它将起作用 命令,但不会阻止 UI。所以我现在很茫然。


繁星coding
浏览 89回答 1
1回答

桃花长相依

您绝不能在JavaFX 应用程序线程上运行长时间运行的任务。这样做将阻止所述线程执行任何导致 UI 冻结的与 GUI 相关的事情。这让您的用户感到难过。但是,您尝试将长时间运行的任务放在后台任务上是有缺陷的。您调用Thread.joinwhich 将阻塞调用线程,直到目标线程死亡;这实际上与在调用线程上运行任务相同。为了快速修复您的示例,您可以执行以下操作:@FXMLprivate void test(){&nbsp; &nbsp; textField.setText("Pending...");&nbsp; &nbsp; Thread t = new Thread(){&nbsp; &nbsp; &nbsp; &nbsp; @Override public void run(){&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; boolean passed = doStuff();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Platform.runLater(() -> {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(passed){&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; textField.setText("OK");&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; textField.setText("Error");&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; });&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; };&nbsp; &nbsp; t.start();}这将创建一个线程,启动它,让它在后台运行,同时让JavaFX 应用程序线程继续做它需要做的事情。在后台线程内部,您必须更新TextField内部Platform.runLater(Runnable)调用。这是必需的,因为您绝不能从 JavaFX 应用程序线程以外的线程更新实时场景图;这样做会导致未定义的行为。此外,您应该查看Java 中的“实现可运行”与“扩展线程”。这样做更好,或者至少更惯用:Thread t = new Thread(() -> { /* background code */ });您还可以使用 a javafx.concurrent.Task,它可以更轻松地与JavaFX Application Thread进行通信。一种选择是:@FXMLprivate void test(){&nbsp; &nbsp; textField.setText("Pending...");&nbsp; &nbsp; Task<Boolean> task = new Task<>() {&nbsp; &nbsp; &nbsp; &nbsp; @Override protected Boolean call() throws Exception {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return doStuff();&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; };&nbsp; &nbsp; task.setOnSucceeded(event -> textField.setText(task.getValue() ? "Ok" : "Error"));&nbsp; &nbsp; new Thread(task).start();}您还可以将 绑定TextField到方法的message属性并在方法内Task调用。如果可能,您甚至可以提供更详细的消息。updateMessage("Pending...")call也就是说,Thread自己创建和启动 s 并不理想,您应该研究线程池(使用类似 an 的东西ExecutorService)。您可能还想研究javafx.concurrent.Service“重用” Tasks。有关 JavaFX 并发的更多信息,请参阅 JavaFX中的并发并阅读javafx.concurrent. 有关 Java 中多线程的基础知识,请参阅课程: Java™ 教程中的并发。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java