текстовое поле javafx не изменяется - PullRequest
0 голосов
/ 12 февраля 2019

У меня есть следующий код:

@FXML
private void test(){
    textField.setText("Pending...");
    boolean passed = doStuff();
    if(passed){
        textField.setText("OK");
    } else {
        textField.setText("Error");
    }
}

И что я пытаюсь добиться, так это то, что пока doStuff () выполняет свои действия в textField в GUI, там должно быть написано «Pending ...»и как только он закончится, он должен измениться на «ОК» / «Ошибка».

Я хочу, чтобы графический интерфейс был заблокирован во время работы doStuff, поэтому пользователь должен ждать и не может щелкнуть что-то еще.

Но что происходит, как только я начинаю тестирование, он выполняет doStuff (), но обновляет только textField с "OK" / "Ошибка", но я никогда не вижу "Ожидание ...".

У меня такое ощущение, что я как-то обновил графический интерфейс, но я не уверен, как это сделать.

Обновление: Я пытался переместить doStuff в другой поток:

@FXML
private void test(){
    textField.setText("Pending...");
    Thread t = new Thread(){
        public void run(){
            boolean passed = doStuff();
            if(passed){
                textField.setText("OK");
            } else {
                textField.setText("Error");
            }
        }
    };
    t.start();
    t.join();
}

Это сработало бы, если бы я удалил t.join ();команда, но тогда пользовательский интерфейс не будет заблокирован.Так что я сейчас в растерянности.

Спасибо

1 Ответ

0 голосов
/ 12 февраля 2019

Вы никогда не должны запускать долго выполняющиеся задачи в Потоке приложений JavaFX .Это будет препятствовать тому, чтобы упомянутый поток делал любые вещи, связанные с GUI, которые приводят к замороженному пользовательскому интерфейсу.Это делает вашего пользователя (ей) грустным.Тем не менее, ваша попытка поставить долгосрочную задачу на фоновую задачу ошибочна.Вы вызываете Thread.join, который блокирует вызывающий поток до тех пор, пока целевой поток не умрет;фактически это то же самое, что просто запустить задачу в вызывающем потоке.

Для быстрого исправления вашего примера вы можете сделать следующее:

@FXML
private void test(){
    textField.setText("Pending...");
    Thread t = new Thread(){
        @Override public void run(){
            boolean passed = doStuff();
            Platform.runLater(() -> {
                if(passed){
                    textField.setText("OK");
                } else {
                    textField.setText("Error");
                }
            });
        }
    };
    t.start();
}

Это создаст поток, запустите его и дайте ему поработать в фоновом режиме, а Поток приложений JavaFX продолжит делать то, что ему нужно.Внутри фонового потока вы должны обновить TextField внутри Platform.runLater(Runnable) вызова.Это необходимо, потому что вы никогда не должны обновлять живой граф сцены из потока, отличного от потока приложения JavaFX ;это приведет к неопределенному поведению.Кроме того, вы должны изучить «реализует Runnable» против «расширяет поток» в Java .Лучше или, по крайней мере, более идиоматично сделать:

Thread t = new Thread(() -> { /* background code */ });

Вы также можете использовать javafx.concurrent.Task, который может упростить связь с приложением JavaFX.тема .Один из вариантов:

@FXML
private void test(){
    textField.setText("Pending...");
    Task<Boolean> task = new Task<>() {
        @Override protected Boolean call() throws Exception {
            return doStuff();
        }
    };
    task.setOnSucceeded(event -> textField.setText(task.getValue() ? "Ok" : "Error"));
    new Thread(task).start();
}

Вы также можете привязать TextField к message свойству Task и вызвать updateMessage("Pending...") внутри метода call.Вы можете даже предоставить более подробные сообщения, если и когда это возможно.

Тем не менее, создание и запуск Thread s сами по себе не идеальны, и вам следует изучить пул потоков (используя что-то вродеExecutorService).Вы также можете обратиться к javafx.concurrent.Service для повторного использования Task с.


Для получения дополнительной информации о параллелизме JavaFX см. Параллельность в JavaFX и прочитайте документацию классов в javafx.concurrent.Для ознакомления с основами многопоточности в Java см. Урок: параллелизм из Учебные руководства Java ™ .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...