Как позволить слушателю работать без зависаний на JavaFX?
Я пытаюсь печатать тексты в режиме реального времени даже после нажатия кнопки.
Когда я нажимаю кнопку, пользовательский интерфейс останавливается, пока его работа не заканчивается, и после этого он печатает все тексты вместе, в отличие от System.out.println.
Код ниже - то, что я попробовал, и он не работает, как я ожидал. Пользовательский интерфейс просто зависает и не показывает мне 'test' на textarea.
Нет необходимости использовать прослушиватель, и можно использовать только appendText, но я просто не могу понять, как позволить ActionEvent для кнопки работать без зависания пользовательского интерфейса.
Я буду очень признателен за любую помощь или гораздо лучший код!
final TextField announcement = new TextField();
Platform.runLater(new Runnable() {
@Override public void run() {
announcement.textProperty().addListener(new javafx.beans.value.ChangeListener<String>() {
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
textoutput.appendText(announcement.getText());
}
});
}
});
btn.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
announcement.setText("test");
// bunch of codes below
}
});
2 ответа
Вы пытались использовать Platform.runLater? У меня есть код, где у меня есть долгосрочные задачи, которые периодически обновляют пользовательский интерфейс с помощью вызовов Platform.runLater(). Это достигается путем запуска Runnable в главном потоке приложения JavaFX, поэтому он выполняется отдельно от вашей длинной задачи.
Например (используя лямбды Java8 - вместо этого вы могли бы просто передать новую реализацию Runnable; для ясности я предпочитаю лямбды в этой ситуации):
btn.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
// Somewhere in your new Task()
Platform.runLater(() -> {
// Update UI
announcement.setText("test");
});
// bunch of codes below
}
});
Причина этого заключается в том, что ваш обработчик событий выполняется в потоке FX, поэтому пользовательский интерфейс не может быть обновлен до его завершения. Как уже было предложено ItachiUchiha, вы должны поместить свой код в Task. Когда вам нужно обновить текст в TextArea, используйте метод Tasks updateMessage (). Поместите ChangeListener в свойство сообщения Tasks и задайте текст из этого прослушивателя.