Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

Good day. I was wondering if there is a convenient or streamlined way of binding FXTask's messageProperty and runningProperty to Label's textProperty and visibleWhen property accordingly without coupling FXTask and Label themselves?

For example in the sample app below, I'm binding messageProperty by coupling label's reference to a task, which introduces an extra lateinit var statusLabel. Similarly, I'm binding runningProperty by coupling task's reference to a label which introduces an extra val task.

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)
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
267 views
Welcome To Ask or Share your Answers For Others

1 Answer

There is a TaskStatus object that can be passed into runAsync. This object has all the interesting properties of the task you're running. No need to subclass Task either :)

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

You could even use the automatically available taskStatus simply by injecting it. If you don't pass a specific instance of TaskStatus to runAsync, you'll get the default instance. Therefor this also works: (Difference is TaskStatus is injected, and no instance of TaskStatus is passed to runAsync)

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...