Избегание не в потоке приложения FX вызывает сбой пользовательского интерфейса - PullRequest
0 голосов
/ 18 октября 2018

Я делаю пошаговую игру на основе JavaFX и использую цикл do while для ожидания ввода пользователя.Проблема в том, что он вызывается из метода инициализации контроллера fxml, и это означает, что интерфейс никогда не загрузится.Решение состоит в том, чтобы подождать, используя другой поток, но JavaFX не позволяет изменять какие-либо узлы из вторичных потоков.

Я избежал получения "Не в потоке приложения FX", используя этот код:

public void initialize(URL arg0, ResourceBundle arg1) {
        // I call the game engine to start the game sequence and I pass root into it for further use
        engine = new GameEngine(root);

        Platform.runLater(new Runnable() {
            @Override
            public void run() {
                engine.start();
            }
          });
    }

в методе engine.start ():

public void start() {
        System.out.println("Game started");
        text("Hello, stranger"); // a new Label inside VBox
        do {
            try {
                Thread.sleep((long) 1000);
                System.out.println("Sleeping...");
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                System.out.println("Error... waiting?");
            }
        } while(this.listener == false); // Listener triggers when user inputs.

        System.out.println("ENTER PRESSED, May proceed");
        text("It worked!");
    }

Кроме того, GameEngine расширяет Thread, и я не знаю, как это влияет на многопоточность.

Когда кодзапущен, пользовательский интерфейс аварийно завершился и выводит Sleeping ... каждую секунду, как следует.

Ответы [ 2 ]

0 голосов
/ 19 октября 2018

В принципе, использование многопоточности должно быть разумным.Один поток ожидает, пока основной поток редактирует макет.Помещение

Platform.runLater(() -> {
  // layout manipulations 
});

вокруг манипуляций с макетом работает, как задумано, если вне основного потока.

0 голосов
/ 18 октября 2018

Вы не можете вызвать цикл Thread.sleep() и / или while в потоке приложений JavaFX, поскольку это приведет к остановке графического интерфейса и ожиданию окончания цикла.

Решениеждать, используя другой поток, но JavaFX не позволяет изменять какие-либо узлы из вторичных потоков.

Да, вы не должны изменять граф сцены из потоков приложений, отличных от JavaFX, но это нене остановит вас от вызова Platform.runLater() для строки (ей) кодов, которые делают фактическую модификацию.Вы также можете использовать Задача для достижения этой цели.

Трудно предложить какое-либо конкретное решение, потому что я понятия не имею, как обновляется флаг listener.

Редактировать

Я не заметил, что метод start() принадлежит подклассу Thread, пока Фабиан не указал на это.Вам никогда не следует переопределять Thread.start(), и, что еще хуже, не вызывать super.start(), когда вы переопределяете его.

Итак, здесь произошло то, что ваш класс GameEngine больше не работает как Thread.Вызов engine.start() просто выполняет любой код, который вы написали в переопределении, в любом вызываемом потоке engine.start() (который является Потоком приложения JavaFX, потому что вы заключили его в Platform.runLater()).

Есливы по-прежнему предпочитаете расширять Thread, тогда вам следует переместить код для переопределения Thread.run().Также обратите внимание, что вы должны удалить Platform.runLater() в initialize() и поместить его в любые коды, которые будут влиять на GUI.

Например:

Platform.runLater(() -> {
    myLabel.setText("User typed" + input);
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...