Как добавить текст в TextArea с задержкой в ​​10 секунд в JavaFX? - PullRequest
0 голосов
/ 12 января 2019

У меня есть эта функция, которая вставляет данные в TextArea, и я хочу добавить текст, каждую итерацию в DisplayChain, через 10 секунд (просто образец). Что я должен использовать?

Вот мой код для DisplayChain:

public void DisplayChain() {    
    for(int i=0;i<chain.size();i++) {
        a.appendText("Block: " + i + "\n");
        a.appendText("Version: " + chain.get(i).getVersion()+ "\n");
        a.appendText("TimeStamp: " + chain.get(i).getTimestamp()+ "\n");
        a.appendText("PreviousHash: " + chain.get(i).getPreviousHash()+ "\n");
        a.appendText("Hash: " + chain.get(i).getHash()+ "\n");
        a.appendText("\n"); 
    }
}

Ответы [ 4 ]

0 голосов
/ 12 января 2019

Используйте Timeline для многократного запуска appendText вызовов для одной "итерации цикла":

final Timeline timeline = Timeline();

EventHandler<ActionEvent> handler = new EventHandler<ActionEvent>() {

    int i = 0;

    @Override
    public void handle(ActionEvent e) {
        if (i >= chain.size()) {
            // stop thread, if index exceeds chain size
            timeline.stop();
        } else {
            // execute a single "loop iteration"
            a.appendText("Block: " + i + "\n"
                         + "Version: " + chain.get(i).getVersion()+ "\n"
                         + "TimeStamp: " + chain.get(i).getTimestamp()+ "\n"
                         + "PreviousHash: " + chain.get(i).getPreviousHash()+ "\n"
                         + "Hash: " + chain.get(i).getHash()+ "\n"
                         + "\n");
            i++;
        }
    }

};
timeline.getKeyFrames().add(new KeyFrame(Duration.seconds(10), handler));
timeline.setCycleCount(Animation.INDEFINITE); // keep timeline running until handler stops it
timeline.play();

Примечание: Я рекомендую извлечь chain.get(i) в локальную переменную, чтобы избежать многократного доступа к коллекции.

0 голосов
/ 12 января 2019

Если я правильно понимаю, вы можете добавить эту строку

Thread.sleep(10000);
0 голосов
/ 12 января 2019

Самый простой подход - использовать метод Thread.sleep, но вы не должны вызывать его в потоке приложения JavaFX. Если бы вы сделали это, вы бы заблокировали само приложение: не было бы отрисовки элементов управления и не отвечало бы на пользовательский ввод с помощью мыши или клавиатуры, пока не завершится ваш спящий вызов.

Это означает, что Thread.sleep нельзя вызвать из обработчика событий или прослушивателя. Чтобы решить эту проблему, вызовите Thread.sleep из совершенно новой темы.

Однако, хотя Thread.sleep нельзя вызывать в потоке приложения, обратное справедливо для методов JavaFX: они должны вызываться из потока приложения. Метод Platform.runLater позволяет сделать это:

Runnable task = () -> {
    try {
        for (int i = 0; i < chain.size(); i++) {
            int index = i;
            Platform.runLater(() -> {
                a.appendText("Block: " + index + "\n");
                a.appendText("Version: " + chain.get(index).getVersion()+ "\n");
                a.appendText("TimeStamp: " + chain.get(index).getTimestamp()+ "\n");
                a.appendText("PreviousHash: " + chain.get(index).getPreviousHash()+ "\n");
                a.appendText("Hash: " + chain.get(index).getHash()+ "\n");
                a.appendText("\n"); 
            });

            Thread.sleep(10000);
        }
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
};
new Thread(task).start();

Причина int index = i; заключается в том, что локальные переменные не могут быть прочитаны другими классами, например, анонимным Runnable, переданным Platform.runLater, если они не являются окончательными (или фактически окончательными).

Приведенный выше код предполагает, что коллекция chain не изменяется. Если это может измениться во время чтения, вы должны сделать chain потокобезопасную коллекцию (например, ConcurrentLinkedDeque или CopyOnWriteArrayList ) или самостоятельно реализовать безопасность потоков, что, вероятно, более сложнее, чем вы предполагали, для кода.

0 голосов
/ 12 января 2019

Вы можете подать заявку javafx.application.Platform:

new Thread ( () -> {
    try {
        Thread.sleep ( delayMs ); // 1000 in this case
        Platform.runLater ( () -> {
            ...
        } );
    } catch ( InterruptedException ie ) { }
} ).start ( );
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...