即使UI线程似乎响应,标签文本也不会更新

我正在使用JDK 8u121上的Kotlin 1.1.51构建TornadoFX 1.7.11的应用程序。

我试图在一个单独的线程中执行长时间运行的任务,并使用进度条和标签在UI中显示进度。 奇怪的是,标签没有更新。 我认为,也许我以某种方式在UI线程上运行的任务,它卡住了,但进度条工作和用户界面是否响应(控制工作等)。

进度条半满并显示消息更新的控制台消息的屏幕截图。一个红色箭头指向标签应该在的地方,但在那里没有文字。

我也尝试用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) } } } } } 

这也可以用少些夸夸其谈,但我不知道你的应用程序的复杂性或要求,所以我尽可能少地改变它:)