亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

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 關注
  • 106 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號