【问题标题】:Threads in JavaFX: Not on FX application threadJavaFX 中的线程:不在 FX 应用程序线程上
【发布时间】:2026-02-18 16:45:01
【问题描述】:

我想学习如何在 JavaFX 中使用线程。例如,2 个进程,应该每 100 毫秒更改一次标签上的文本,并且每 100 毫秒更新一次屏幕上的信息。

但在这种情况下它不起作用。 IDEA 写道:

线程“Thread-4”java.lang.IllegalStateException 中的异常:不在 FX 应用程序线程上; currentThread = Thread-4

我已经阅读了许多具有相同问题的示例,但他们的任何解决方案都不起作用。

我该怎么办?

谢谢。

sample.fxml

...
<Button fx:id="startBut" layoutX="100.0" layoutY="50.0" mnemonicParsing="false" onAction="#testingOfThread" prefHeight="25.0" prefWidth="65.0" text="Export" />
<Label fx:id="firstStatus" layoutX="100.0" layoutY="100" text="Status" />
<Label fx:id="secondStatus" layoutX="100.0" layoutY="150" text="Status" />
...

Main.java

package sample;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception{
        Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
        primaryStage.setTitle("Sample");
        primaryStage.setScene(new Scene(root));
        primaryStage.show();
    }

    //Take control to Controller
    public void initializeController(){
        FXMLLoader loader = new FXMLLoader();
        Controller controller = loader.getController();
        controller.setMain(this);
    }

    public static void main(String[] args) {
        launch(args);
    }
}

Controller.java

package sample;

import javafx.concurrent.Task;
import javafx.fxml.FXML;
import javafx.scene.control.*;

public class Controller {

    @FXML
    private Label firstStatus;

    @FXML
    private Label secondStatus;

    @FXML
    public Button startBut;


    //Link to MainApp
    private Main Main;

    //Constructor
    public Controller(){
    }


    //Link for himself
    public void setMain(Main main){
        this.Main = main;
    }

    @FXML
    private void testingOfThread(){

        Task<Void> task = new Task<Void>() {
            @Override public Void call() {
                for (int i = 0; i < 100; i++) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        Thread.interrupted();
                        break;
                    }
                    System.out.println(i + 1);
                    firstStatus.setText(i+"");
                }
                return null;
            }
        };

        Thread th = new Thread(task);
        th.setDaemon(true);
        th.start();


        Task<Void> task2 = new Task<Void>() {
            @Override public Void call() {
                for (int i = 0; i < 100; i++) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        Thread.interrupted();
                        break;
                    }
                    System.out.println(i + 1);
                    secondStatus.setText(i+"");
                }
                return null;
            }
        };

        Thread th2 = new Thread(task2);
        th2.start();

    }
}

【问题讨论】:

  • 不要从应用程序线程以外的线程更新 GUI。您需要使用Platform.runLater。或者,既然您已经在使用任务,请使用 updateMessage 更新 message 属性而不是 text 属性,并将 text 属性绑定到 message 属性:call 方法:/* firstStatus.setText(i+"");*/ updateMessage(Integer.toString(i)); 之前启动线程:firstStatus.textProperty().bind(task.messageProperty());
  • Danke schön,费边!所有作品。

标签: multithreading javafx


【解决方案1】:

从应用程序线程以外的线程中找到更新 GUI 的代码,然后将它们放入 runLater() 中。

Platform.runLater(new Runnable() {
    @Override
    public void run() {
        //update application thread
    }
});

【讨论】: