El text de la label no se actualiza aunque el hilo de la interfaz de usuario parece responder

Estoy construyendo una aplicación con TornadoFX 1.7.11 usando Kotlin 1.1.51 en JDK 8u121.

Estoy intentando ejecutar una tarea de larga duración en un hilo separado y mostrar el progreso en la UI usando una barra de progreso y una label. Extrañamente, la label no se está actualizando. Pensé que tal vez de alguna manera ejecuté la tarea en el hilo de la interfaz de usuario y está atascado, pero la barra de progreso funciona y la interfaz de usuario es receptiva (controles de trabajo, etc.).

Captura de pantalla con barra de progreso medio llena y mensajes de consola que muestran que el mensaje se ha actualizado. Una flecha roja apunta a un lugar donde debe estar la etiqueta, pero no hay texto visible allí.

También intenté editar manualmente la label con ScenicView y funcionó. No tengo ideas, ¿pueden ayudarme?

Aquí hay fragments de código algo simplificados:

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) } } } } } 

Su código no es ejecutable, pero creé una muestra mínima basada en estos conceptos, utilizando un enfoque más idiomático.

 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) } } } } } 

Esto también se puede hacer con less fanfarria, pero no conozco la complejidad o los requisitos de tu aplicación, así que la cambié lo less posible 🙂

  • Columnas de tabla dinámica
  • TornadoFX - Creación de un layout MVP
  • preguntas sobre DI, ViewModel, etc.
  • Tornadofx Javafx - Cómo volver a cargar una vista / componente
  • Animación consecutiva en TornadoFX?
  • TornadoFX - eliminar elemento con ContextMenu hacer clic derecho
  • Lanzar una aplicación TornadoFX desde (un progtwig existente) de Kotlin
  • TornadoFX cómo enlazar Node style (o styleClass) a una propiedad?
  • CellCache se representa inesperadamente en TableView con tornadoFX
  • Cómo mostrar datos usando la vista de tree de TornadoFX
  • TornadoFX JavaFX Sync Desplazarse por las vistas de tabla