【问题标题】:Why am I getting “Not on FX application thread” on JavaFX?为什么我在 JavaFX 上收到“不在 FX 应用程序线程上”?
【发布时间】:2019-08-10 22:13:45
【问题描述】:

我正在学习 JavaFX,并制作了一个带有标签的演示应用程序,该应用程序检测值更改并更改其显示。我试图将 Label.textProperty 绑定到该值,但仍然不起作用。这是我的代码:

public class MainApp extends Application {

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

private Temp aTemp = new Temp();

@Override
public void start(Stage primaryStage) {

    try {
        FXMLLoader loader = new FXMLLoader(getClass().getResource("Sample.fxml"));      
        BorderPane root = (BorderPane)loader.load();
        SampleController sampleController = loader.getController();

        Scene scene = new Scene(root,600,600);
        scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());

        primaryStage.setScene(scene);
        primaryStage.show();

        sampleController.setModel(aTemp);

    } catch(Exception e) {
        e.printStackTrace();
    }
}}

这是模型

public class Temp {
private StringProperty temp = new SimpleStringProperty("a");

private final ExecutorService service = Executors.newCachedThreadPool();

public Temp() {

    task.startConnection();
    service.submit(new Task<Integer>() {

        @Override
        public Integer call() {
            while(true) {
                try {
                    Thread.sleep(1000);
                }catch(Exception e) {
                    e.printStackTrace();
                }

                setTemp(getTemp() + "b");
                System.out.println(getTemp());

            }
        }
    });
}

public StringProperty getProperty() {
    return this.temp;
}

public String getTemp() {
    return this.temp.get();
}

public void setTemp(String value) {
    this.temp.set(value);
}

然后是控制器

public class SampleController implements Initializable {

private Temp aTemp;

@FXML private Label tempLabel;


@Override
public void initialize(URL arg0, ResourceBundle arg1) {


}

public void setModel(Temp aTemp) {
    this.aTemp = aTemp;

    Platform.runLater(new Runnable() {
        @Override
        public void run() {
            tempLabel.textProperty().bind(aTemp.getProperty());
        }
    });

}}

我得到的是标签更改为“a”但之后不会更改,并且出现此异常:

Exception in thread "pool-2-thread-1" 
java.lang.IllegalStateException: Not on FX application thread; currentThread = pool-2-thread-1

【问题讨论】:

  • 您在哪一行得到异常?
  • 您必须在 Platform.runlater 中包装 temp 值的设置:因为标签的文本绑定到该属性,您可以有效地从 fx 应用程序线程更改节点的属性(这是不允许的,正如错误告诉你的那样:)
  • @steven35 at gui.Temp.setTemp(this.temp.set(value);) 和 gui.Temp$1.call(即 setTemp(getTemp() + "b");)
  • @kleopatra 是正确的;或者,您可以在 Task&lt;Integer&gt; 中调用 update value() 并监听 FX 应用程序线程上的更改。
  • @kleopatra 是否意味着我只能在 Platform.runlater 中更改 temp 的值?如何在单独的模型类中做到这一点?

标签: java multithreading javafx


【解决方案1】:

充实我的评论:如果您想让模型完全不知道 UI,那么不要将它直接绑定到控件的属性。取而代之的是,在 UI 端有一些模型属性的侦听器来更改 fx 线程上的控制属性。

代码 sn-p(未经测试,只是复制和调整 - 所以甚至可能无法编译;):

public void setModel(Temp aTemp) {
    this.aTemp = aTemp;

    aTemp.tempProperty().addListener(this::updateLabelText) 

}}

private void updateLabelText() {
   Platform.runLater(() -> label.setText(aTemp.getTemp()));  
} 

【讨论】:

    猜你喜欢
    • 2013-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-24
    • 1970-01-01
    • 2014-01-31
    • 2016-12-07
    相关资源
    最近更新 更多