JavaFX: автоматическая прокрутка TextArea с appendText, но без прослушивателей
Я читал другие статьи на Stackru на эту тему. Но ни один из них точно не соответствует моей проблеме.
Я хочу войти в алгоритм в TextArea. На каждой итерации алгоритма текст в этой TextArea должен быть расширен с помощью appendText().
Моя первая проблема: где я должен создать новый поток и как оба потока могут общаться друг с другом (графический интерфейс и алгоритм)?
В моем реальном дизайне у меня есть три важных класса: представление, которое содержит TextArea, контроллер, который вызывает алгоритм, и алгоритм, который принимает несколько итераций, и TextArea (для вызова appendText()- метода в местах разделения. в коде).
В этой схеме контроллер вызывает алгоритм, алгоритм итерирует n раз с циклом for, и после его завершения GUI показывает изменения. Но я хочу, чтобы графический интерфейс отображал изменения одновременно, когда алгоритм вызывает метод appendText().
И моя вторая проблема - это автопрокрутка TextArea. После каждого вызова appendText TextArea следует полностью прокрутить вниз. Но я думаю, что решение этой проблемы - то же самое решение моей первой проблемы.
Буду очень признателен за помощь.
1 ответ
Практически невозможно полностью ответить на ваш вопрос без (большого количества) дополнительной информации, но общий подход, который я бы использовал, состоял в том, чтобы алгоритм имел обратный вызов для обработки сообщения, который может быть вызван каждым шагом алгоритма. От контроллера передайте реализацию обратного вызова, который обновляет текстовую область сообщением в Потоке Приложения FX.
Что-то вроде:
public class Algorithm {
private Consumer<String> statusCallback ;
public Algorithm(Consumer<String> statusCallback) {
this.statusCallback = statusCallback ;
}
public Algorithm() {
// by default, callback does nothing:
this(s -> {});
}
public void performAlgorithm() {
while (! finished() ) {
doNextStep();
String statusMessage = getStatus();
statusCallback.accept(statusMessage);
}
}
}
а потом
public class Controller {
private View view = ... ;
public void startAlgorithm() {
Algorithm algorithm = new Algorithm(s -> Platform.runLater(view.appendStatus(s)));
Thread t = new Thread(algorithm::performAlgorithm);
t.setDaemon(true);
t.start();
}
}
Для View
Затем вы делаете следующее (обратите внимание, что вы можете прокрутить вниз textArea.setScrollTop(Double.MAX_VALUE);
):
public class View {
private TextArea textArea ;
public View() {
textArea = new TextArea();
// ...
}
public void appendStatus(String status) {
if (!textArea.getText().isEmpty()) {
textArea.appendText("\n");
}
textArea.appendText(status);
textArea.setScrollTop(Double.MAX_VALUE);
}
}
Это должно работать, пока ваш алгоритм не создает слишком много обновлений статуса слишком быстро (чтобы они заполняли поток приложений FX и не позволяли ему выполнять свою обычную работу).