从不同 class 中的不同线程修改 JavaFX gui

Modifying JavaFX gui from different thread in different class

我正在尝试创建一个环境,在其中设置了 GUI,当用户通过侦听器修改其组件时,另一个线程每隔 X 秒向其添加新元素。 (这是一个游戏,是的)

我希望游戏在一个 class 中,而 "element adder" 线程在另一个中 - 但当然 Java 抱怨我无法修改 JavaFX GUI来自另一个线程。

我见过使用 Platform.runLater() 的解决方案,但据我所知,所有这些解决方案都使用匿名内部 classes。我真的希望我的加法器在另一个(命名)class.

任何提示都将不胜感激,这里是代码的最小版本,可重现问题:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;

public class DifferentThreadJavaFXMinimal extends Application {

    private Thread t;
    private GridPane gp;

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

    @Override
    public void start(Stage primaryStage) throws Exception {
        gp = new GridPane();
        Scene gameScene = new Scene(gp, 600,500);
        primaryStage.setScene(gameScene);

        t = new Thread(new Thread2(instance()));




        primaryStage.show();
        t.start(); 
    }
    void addElement(int i) {
        Button actualButton = new Button("TEST");
        gp.add(actualButton,i,i);
    }
    public DifferentThreadJavaFXMinimal instance(){
        return this;
    }

}

class Thread2 implements Runnable {
    private DifferentThreadJavaFXMinimal d;

    Thread2(DifferentThreadJavaFXMinimal dt){
        d=dt;
    }

    @Override
    public void run() {
        for (int i=0;i<4;i++) {
        d.addElement(i);
        }
    }

}

您仍然可以使用独立的 class。

规则是对 UI 的更改必须发生在 FX 应用程序线程上。您可以通过包装来自其他线程的调用来导致这种情况发生,这些线程会更改您传递给 Platform.runLater(...).

Runnable 中的 UI

在您的示例代码中,d.addElement(i) 更改了 UI,因此您可以:

class Thread2 implements Runnable {
    private DifferentThreadJavaFXMinimal d;

    Thread2(DifferentThreadJavaFXMinimal dt){
        d=dt;
    }

    @Override
    public void run() {
        for (int i=0;i<4;i++) {
            final int value = i ;
            Platform.runLater(() -> d.addElement(value));
            // presumably in real life some kind of blocking code here....
        }
        System.out.println("Hahó");
    }

}