Текст ярлыка не обновляется, хотя поток пользовательского интерфейса кажется отзывчивым

Я создаю приложение с TornadoFX 1.7.11, используя Kotlin 1.1.51 на JDK 8u121.

Я пытаюсь выполнить долговременную задачу в отдельном потоке и показать прогресс в пользовательском интерфейсе, используя панель прогресса и метку. Как ни странно, ярлык не обновляется. Я подумал, что, возможно, я как-то запустил задачу в потоке пользовательского интерфейса, и он застрял, но работает progressbar и пользовательский интерфейс реагирует иначе (управление работает и т. Д.).

Снимок экрана с полузаполненными промежуточными сообщениями и консольными сообщениями, показывающими, что сообщение обновлено. Красная стрелка указывает на место, где должна быть метка, но там нет текста.

Я также попытался вручную отредактировать ярлык с помощью ScenicView, и он сработал. У меня нет идей, вы можете помочь?

Вот несколько упрощенных фрагментов кода:

MainView.kt

class MainView : View("") { private val controller: MainController by inject() override val root = borderpane { bottom(TasksView::class) } init { controller.reloadTranslations().completed.onChange { // do some lightweight UI stuff } } } 

MainController.kt

 class MainController : Controller() { private val tasksController: TasksController by inject() fun reloadTranslations(): TaskStatus { val task = TaskStatus() tasksController.tasks.add(task) runAsync(task) { updateMessage(messages["loadingTranslations"]) BibxCache.rebuild().subscribe { updateMessage(messages["loadingTranslations"] + " " + it.loaded) // for debugging updateProgress(it.loaded.toLong(), it.total.toLong()) } } return task } fun getTranslations() = BibxCache.values.toSortedSet() } 

TasksView.kt

 class TasksView : View() { override val root = vbox() val controller: TasksController by inject() init { controller.tasks.onChange { root.clear() controller.tasks.map { TaskRow(it) }.forEach { root.add(it) } } } } class TaskRow(task: TaskStatus) : HBox() { init { val progressBar = ProgressBar(task.progress.get()) progressBar.bind(task.progress) val label = Label(task.message.get()) label.bind(task.message) task.message.onChange { println(it) } // for debugging children.addAll( progressBar, Label(task.message.get()) ) } } 

TasksController.kt

 class TasksController : Controller() { val tasks: ObservableList<TaskStatus> = FXCollections.observableArrayList() init { tasks.onChange { change -> change.next() change.addedSubList.forEach { added -> added.completed.onChange { tasks.remove(added) } } } } } 

Ваш код не работает, но я создал минимальный образец на основе этих понятий, используя более идиоматический подход.

 class MainView : View("Tasks") { private val mainController: MainController by inject() override val root = borderpane { setPrefSize(600.0, 400.0) top { button("Start task").action { mainController.reloadTranslations() } } bottom(TasksView::class) } } class MainController : Controller() { private val tasksController: TasksController by inject() fun reloadTranslations(): TaskStatus { val task = TaskStatus() tasksController.tasks.add(task) runAsync(task) { updateMessage(messages["loadingTranslations"] + " $this...") Thread.sleep(Random().nextInt(2000).toLong()) updateMessage(messages["loadingTranslations"] + " $this - half way") updateProgress(50.0, 100.0) Thread.sleep(Random().nextInt(2000).toLong()) } return task } } class TasksView : View() { val controller: TasksController by inject() override val root = vbox { bindChildren(controller.tasks) { task -> hbox { progressbar(task.progress) label(task.message) } } } } class TasksController : Controller() { val tasks: ObservableList<TaskStatus> = FXCollections.observableArrayList() init { tasks.onChange { change -> change.next() change.addedSubList.forEach { added -> added.completed.onChangeOnce { tasks.remove(added) } } } } } 

Это также можно сделать с меньшим количеством фанфаров, но я не знаю сложности или требований вашего приложения, поэтому я изменил его как можно меньше 🙂