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 и не позволяли ему выполнять свою обычную работу).

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