为什么在JavaFX上显示“不在FX应用程序线程上”?

时间:2019-03-20 09:05:04

标签: java multithreading javafx

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

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());
        }
    });

}}

我得到的是Label更改为“ a”,但此异常之后将不会更改:

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

1 个答案:

答案 0 :(得分:4)

充实我的评论:如果您想让模型完全不知道UI,则不要将其直接绑定到控件的属性。而是在UI端对model属性进行一些监听,以更改fx线程上的control属性。

一个代码段(未经测试,仅进行了复制和调整-因此可能甚至无法编译;):

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

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

}}

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