Почему я получаю «Нет в потоке приложений FX» на JavaFX? - PullRequest
2 голосов
/ 20 марта 2019

Я изучаю 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());
        }
    });

}}

Что я получил, так это то, что Label изменилось на «a», но не изменится после, и это исключение:

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

1 Ответ

4 голосов
/ 20 марта 2019

Чтобы конкретизировать мой комментарий: если вы хотите, чтобы модель полностью не знала об интерфейсе пользователя, не связывайте ее напрямую со свойством элемента управления. Вместо этого на стороне пользовательского интерфейса есть слушатель свойства модели, который изменяет свойство элемента управления в потоке FX.

Фрагмент кода (не тестировался, просто копировался и корректировался, поэтому может даже не компилироваться;):

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

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

}}

private void updateLabelText() {
   Platform.runLater(() -> label.setText(aTemp.getTemp()));  
} 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...