Я разрабатываю приложение с несколькими объектами TextField
, которые необходимо обновить, чтобы отражать изменения связанных свойств back-end. TextField
не редактируются, только исходный код может изменять их содержимое.
Как я понимаю, правильный способ - запустить тяжелое вычисление в отдельном потоке, чтобы не блокировать пользовательский интерфейс. Я сделал это с помощью javafx.concurrent.Task
и передал одно значение обратно в поток JavaFX с помощью updateMessage()
, который работал хорошо. Тем не менее, мне нужно больше, чем одно значение, которое нужно обновить, так как back-end делает хруст.
Так как базовые значения хранятся как свойства JavaFX, я попробовал просто привязать их к textProperty
каждого элемента GUI и позволить привязкам выполнять работу. Однако это не работает; после запуска в течение нескольких секунд, TextField
перестанет обновляться, даже если задняя задача все еще запущена. Никаких исключений не возникает.
Я также попытался использовать Platform.runLater()
для активного обновления TextField
вместо привязки. Проблема здесь в том, что задачи runLater()
планируются быстрее, чем платформа может их запускать, поэтому графический интерфейс становится вялым и требует времени, чтобы "догнать" даже после завершения конечной задачи.
Я нашел здесь несколько вопросов:
Записи регистратора, переведенные на пользовательский интерфейс, перестают обновляться со временем
Многопоточность в JavaFX висит в пользовательском интерфейсе
но моя проблема сохраняется.
Вкратце: у меня есть фоновый ввод изменений в свойствах, и я хочу, чтобы эти изменения появлялись в графическом интерфейсе. Back-end - это генетический алгоритм, поэтому его работа разбивается на дискретные поколения. Я бы хотел, чтобы TextField
обновлялся хотя бы один раз между поколениями, даже если это задерживает следующее поколение. Более важно, чтобы GUI реагировал хорошо, чем GA быстро работает.
Я могу опубликовать несколько примеров кода, если я не сделал проблему ясной.
UPDATE
Мне удалось сделать это после предложения James_D. Чтобы решить проблему, когда серверу приходилось ждать, пока консоль будет печатать, я применил буферизованную консоль. Он сохраняет строки для печати в StringBuffer
и фактически добавляет их к TextArea
при вызове метода flush()
. Я использовал AtomicBoolean, чтобы предотвратить следующее поколение, пока поток не будет завершен, как это сделано с помощью Platform.runLater()
runnable. Также обратите внимание, что это решение невероятно медленно.