gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-02 13:14:28 25 4
gpt4 key购买 nike

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

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

Screenshot with progressbar half-filled and console messages showing that message is updated. A red arrow is pointing to a place where label should be, but no text is visible there.

我还尝试过使用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)
}
}
}
}
}

也可以大张旗鼓地做到这一点,但是我不知道您的应用程序的复杂性或要求,因此我尽可能少地对其进行了更改:)

关于multithreading - 即使UI线程似乎响应,标签文本也不会更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46884079/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com