我正在JDK 8u121上使用Kotlin 1.1.51在TornadoFX 1.7.11上构建应用程序。
我正在尝试在单独的线程中执行长时间运行的任务,并使用进度条和标签在UI中显示进度。奇怪的是,标签没有更新。我想也许我不知何故在UI线程上运行任务并且它被卡住了,但是进度条工作并且UI响应(控制工作等)。
我还尝试使用ScenicView手动编辑标签,但它确实有效。我没有想法,你们可以帮忙吗?
以下是一些简化的代码片段:
MainView.ktclass 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)
}
}
}
}
}
答案 0 :(得分:3)
您的代码不可运行,但我使用更惯用的方法创建了基于这些概念的最小样本。
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)
}
}
}
}
}
这也可以通过较少的大张旗鼓来完成,但我不知道你的应用程序的复杂性或要求,所以我尽可能少地改变它:)