Каков наилучший способ обновить TextArea из Задачи построчно? - PullRequest
0 голосов
/ 14 марта 2019

Я выполняю скрипт из своего приложения и обновляю текстовую область выводом через прослушиватель изменений в свойстве Значение задачи, но отображаются не все строки.

this.valueProperty().addListener(new ChangeListener<String>() {

    @Override
    public void changed(ObservableValue observable, String oldValue, String newValue) {
        if (!(newValue == null)) {
            output.appendText(newValue + "\n");
        }
    }

});

Моя проблема в основном решена в JavaFX ChangeListener не всегда работает , но у меня есть дополнительный вопрос.

Сон Задачи до или после вызова updateValue (), кажется, имеет желаемый результат непрерывного добавления результата, но я не понимаю, как. По мере того как время сна уменьшается, результат становится все более и более неполным. Если задание спит, разве оно не подхватит там, где остановилось, и я не увижу никакой разницы в поведении? Поскольку свойство объединенного значения не изменилось?

Или спящий поток гарантирует, что значение не будет обновлено в течение следующих 250 миллисекунд, а поток пользовательского интерфейса будет обновляться в это время? И это дает потоку пользовательского интерфейса достаточно времени для захвата каждой строки? Это не похоже на очень надежный способ обновления, потому что, как я узнаю, сколько времени нужно, чтобы получить полный вывод?

    while ((line = outputReader.readLine()) != null) {
        updateValue(line);
        Thread.sleep(250);
    }

Я пытался обновить TextArea напрямую через Platform.runLater после прочтения каждой строки, но я получаю ошибку «локальная переменная, на которую ссылается внутренний класс», и я не мог понять, как обойти это. TexArea - это переменная экземпляра моего расширенного класса Task, и она не является окончательной, поскольку я добавляю строки, поэтому не знаю, как это сделать.

1 Ответ

0 голосов
/ 14 марта 2019

Task.updateValue гарантирует, что обновление произойдет в будущем. Поскольку планирование этих обновлений является дорогостоящим, оно просто гарантирует, что будет обновление до последнего переданного значения. Работает аналогично этому

void updateValue(T value) {
    setNewValue(value);
    if (lastUpdateFinished()) {
        Platform.runLater(() -> doUpdate());
    }
}

Где lastUpdateFinished возвращает false тогда и только тогда, когда запланировано обновление, которое еще не получило новое значение. Теоретически никакое количество сна не является гарантией предотвращения проблем, но на практике, чем дольше вы спите, тем больше вероятность того, что lastUpdateFinished() даст true за каждый звонок updateValue ...


В вашем случае Platform.runLater необходимо использовать несколько раз, чтобы поток приложений видел каждое обновление:

String line;
while ((line = outputReader.readLine()) != null) {
    final String lineFinal = line + "\n";
    Platform.runLater(() -> output.appendText(lineFinal));
}

Обратите внимание, что это может замедлить работу JavaFX, если обновления появляются слишком часто.

...