Как позволить слушателю работать без зависаний на 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 и задайте текст из этого прослушивателя.

Другие вопросы по тегам