为了账号安全,请及时绑定邮箱和手机立即绑定

javafx 文本字段没有改变

javafx 文本字段没有改变

繁星coding 2022-06-15 17:22:39
我有以下代码:@FXMLprivate 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 移到另一个线程中:@FXMLprivate 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。所以我现在很茫然。
查看完整描述

1 回答

?
桃花长相依

TA贡献1860条经验 获得超8个赞

您绝不能在JavaFX 应用程序线程上运行长时间运行的任务。这样做将阻止所述线程执行任何导致 UI 冻结的与 GUI 相关的事情。这让您的用户感到难过。但是,您尝试将长时间运行的任务放在后台任务上是有缺陷的。您调用Thread.joinwhich 将阻塞调用线程,直到目标线程死亡;这实际上与在调用线程上运行任务相同。


为了快速修复您的示例,您可以执行以下操作:


@FXML

private void test(){

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

    Thread t = new Thread(){

        @Override public void run(){

            boolean passed = doStuff();

            Platform.runLater(() -> {

                if(passed){

                    textField.setText("OK");

                } else {

                    textField.setText("Error");

                }

            });

        }

    };

    t.start();

}

这将创建一个线程,启动它,让它在后台运行,同时让JavaFX 应用程序线程继续做它需要做的事情。在后台线程内部,您必须更新TextField内部Platform.runLater(Runnable)调用。这是必需的,因为您绝不能从 JavaFX 应用程序线程以外的线程更新实时场景图;这样做会导致未定义的行为。此外,您应该查看Java 中的“实现可运行”与“扩展线程”。这样做更好,或者至少更惯用:


Thread t = new Thread(() -> { /* background code */ });

您还可以使用 a javafx.concurrent.Task,它可以更轻松地与JavaFX Application Thread进行通信。一种选择是:


@FXML

private void test(){

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

    Task<Boolean> task = new Task<>() {

        @Override protected Boolean call() throws Exception {

            return doStuff();

        }

    };

    task.setOnSucceeded(event -> textField.setText(task.getValue() ? "Ok" : "Error"));

    new Thread(task).start();

}

您还可以将 绑定TextField到方法的message属性并在方法内Task调用。如果可能,您甚至可以提供更详细的消息。updateMessage("Pending...")call


也就是说,Thread自己创建和启动 s 并不理想,您应该研究线程池(使用类似 an 的东西ExecutorService)。您可能还想研究javafx.concurrent.Service“重用” Tasks。


有关 JavaFX 并发的更多信息,请参阅 JavaFX中的并发并阅读javafx.concurrent. 有关 Java 中多线程的基础知识,请参阅课程: Java™ 教程中的并发。


查看完整回答
反对 回复 2022-06-15
  • 1 回答
  • 0 关注
  • 88 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信