Как заставить UI javafx обновится?
Подскажите пожалуйста, как заставить UI обновится?
Мне нужно, чтобы перед началом обработки устанавливался текст:
info.setText("Calculating");
А второй поток должен ждать окончания выполнения первого, потому что он будет делать свои дела на основе вычислений первого, но из-за строки
Runnable updater = () -> info.setText("qwer");
Не хочет устанавливаться текст "Calculating".
То есть мне нужно сначала оповестить пользователя что идут какие-то вычисления, а потом сказать что начался второй этап вычислений.
info.setText("Calculating");
Thread thread = new Thread(() -> {
Runnable updater = () -> {
int total = calculate(fileZ, fileT);
info.setText("0 from " + total);
};
Platform.runLater(updater);
});
thread.setDaemon(true);
thread.start();
Thread thread2 = new Thread(() -> {
Runnable updater = () -> info.setText("qwer");
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
Platform.runLater(updater);
});
thread2.setDaemon(true);
thread2.start();
Ответы (1 шт):
То что вы оборачиваете в Platform.runLater выполнится не в текущем потоке, а в потоке javafx через какое-то время. По сути поток thread поручает потоку javafx выполнить какой-то действие (запустить calculate, изменить текст метки), а сам сразу завершается, не дожидаясь окончания выполнения метод calculate, и поток thread2 сразу продолжает свое выполнение.
Чтобы в первом потоке дождаться завершения выполнения метода calculate, этот метод не должен быть обернут в runLater:
info.setText("Calculating");
Thread thread = new Thread(() -> {
int total = calculate(fileZ, fileT);
Platform.runLater(() -> info.setText("0 from " + total));
});
thread.setDaemon(true);
thread.start();
Thread thread2 = new Thread(() -> {
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
Platform.runLater(() -> info.setText("qwer"));
});
thread2.setDaemon(true);
thread2.start();
Если у вас внутри calculate есть, например, вывод в метку текущего прогресса, то этот вывод нужно обернуть в runLater (не весь метод calculate, не цикл, в котором есть вывод, а только вывод).
Также, для выполнения нескольких действий по цепочке в отдельном потоке удобно использовать CompletableFuture:
info.setText("Calculating");
CompletableFuture.runAsync(() -> {
int total = calculate(fileZ, fileT);
Platform.runLater(() -> info.setText("0 from " + total));
}).thenRun(() -> {
Platform.runLater(() -> info.setText("qwer"));
}).exceptionally(throwable -> {
throwable.printStackTrace();
return null;
});