Kotlin 将`FXTask`消息绑定到`Label`而不在FX中进行组件耦合

Kotlin 将`FXTask`消息绑定到`Label`而不在FX中进行组件耦合,kotlin,tornadofx,Kotlin,Tornadofx,你好。我想知道是否有一种方便或简化的方法可以将fxstask的messageProperty和runningProperty绑定到Label的textProperty和Label属性,而不耦合fxstask和本身 例如,在下面的示例应用程序中,我通过将标签的引用耦合到任务来绑定messageProperty,这引入了一个额外的lateinit var statusLabel。类似地,我通过将任务的引用耦合到一个标签来绑定runningProperty,该标签引入了一个额外的val任务 class

你好。我想知道是否有一种方便或简化的方法可以将
fxstask
messageProperty
runningProperty
绑定到
Label
textProperty
Label
属性,而不耦合
fxstask
本身

例如,在下面的示例应用程序中,我通过将标签的引用耦合到任务来绑定
messageProperty
,这引入了一个额外的
lateinit var statusLabel
。类似地,我通过将任务的引用耦合到一个标签来绑定
runningProperty
,该标签引入了一个额外的
val任务

class DummyView : View("Dummy View") {
    override val root = vbox {
        lateinit var statusLabel: Label

        val task = object : Task<Void>() {
            public override fun call(): Void? {
                Platform.runLater { statusLabel.textProperty().bind(messageProperty()) } // label coupling

                updateMessage("Initializing task...")
                (1..3).forEach {
                    Thread.sleep(1000)
                    updateMessage("Doing task: $it...")
                }

                Thread.sleep(1000)
                updateMessage("Task done")
                Thread.sleep(1000)
                return null
            }
        }

        button("Do task") {
            action {
                Thread(task).apply {// task coupling
                    isDaemon = true
                }.start()
            }
        }
        statusLabel = label("Status") {
            visibleWhen(task.runningProperty()) // task coupling
        }
    }
}

class DummyApp : App(DummyView::class)
class DummyView:View(“虚拟视图”){
覆盖val root=vbox{
lateinit var状态标签:标签
val task=object:task(){
public override fun call():Void{
Platform.runLater{statusLabel.textProperty().bind(messageProperty())}//标签耦合
updateMessage(“正在初始化任务…”)
(1..3)forEach{
线程。睡眠(1000)
updateMessage(“正在执行任务:$it…”)
}
线程。睡眠(1000)
更新消息(“任务完成”)
线程。睡眠(1000)
返回空
}
}
按钮(“执行任务”){
行动{
线程(任务)。应用{//任务耦合
isDaemon=true
}.start()
}
}
statusLabel=标签(“状态”){
visibleWhen(task.runningProperty())//任务耦合
}
}
}
类DummyApp:App(DummyView::类)

有一个
TaskStatus
对象可以传递到
runAsync
中。此对象具有您正在运行的任务的所有有趣属性。无需子类化
任务
或:)

您甚至可以通过注入自动可用的taskStatus来使用它。如果未将TaskStatus的特定实例传递给runAsync,则将获得默认实例。因此,这也是可行的:(区别在于TaskStatus被注入,TaskStatus的任何实例都不会传递给runAsync)


谢谢,这正是我想要的。我还有一个问题:何时首选创建
TaskStatus
的实例,何时首选注入它?每种方法的优缺点是什么?如果没有对任务的引用,如何取消该任务?注入的
TaskStatus
由在同一范围内运行的每个异步作业共享,因此这样做非常方便。如果需要更严格的控制,或者希望在ui中同时显示多个任务的进度,则需要实例化单独的
TaskStatus
对象,并将它们传递到每个
runAsync
调用中。要取消任务,可以插入任务和调用站点都可以访问的ViewModel。您还可以手动实例化一个对象并将其传入。如果在该对象内的属性中设置了某个值,则任务将知道如何取消。
class DummyView : View("Dummy View") {
    val taskStatus = TaskStatus()

    override val root = vbox {
        button("Do task") {
            action {
                runAsync(taskStatus) {
                    updateMessage("Initializing task...")
                    (1..3).forEach {
                        Thread.sleep(1000)
                        updateMessage("Doing task: $it...")
                    }
                    Thread.sleep(1000)
                    updateMessage("Task done")
                    Thread.sleep(1000)
                }
            }
        }
        label(taskStatus.message) {
            visibleWhen(taskStatus.running)
        }
    }
}
class DummyView : View("Dummy View") {
    val taskStatus: TaskStatus by inject()

    override val root = vbox {
        button("Do task") {
            action {
                runAsync {
                    updateMessage("Initializing task...")
                    (1..3).forEach {
                        Thread.sleep(1000)
                        updateMessage("Doing task: $it...")
                    }
                    Thread.sleep(1000)
                    updateMessage("Task done")
                    Thread.sleep(1000)
                }
            }
        }
        label(taskStatus.message) {
            visibleWhen(taskStatus.running)
        }
    }
}