从不同 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ó");
}
}
我正在尝试创建一个环境,在其中设置了 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ó");
}
}