无法使用http发布进度更新标签。 IllegalStateException

时间:2019-05-17 00:40:50

标签: kotlin tornadofx

我在将UI组件绑定到可观察对象上遇到麻烦,该可观察对象从http发布事件获取更新进度。我收到一个IllegalStateException

据我了解,问题是UI线程上没有发生绑定更新。我已经读过的答案说,我需要使用runAsync,然后指定一个UI块来更新UI组件,但是我对如何完成此操作感到困惑。

// View class
private val controller: ZumController by inject()

item("_Upload") {
    isMnemonicParsing = true
    action {
       controller.uploadToServer()
    }
}

bottom = label() {
    useMaxWidth = true
    padding = Insets(5.0, 10.0, 5.0, 10.0)
    this.bind(controller.progress)
}

// Controller class
var progress = SimpleStringProperty("Select images to upload")

fun uploadToServer() {
    images.forEach{ p ->
        Fuel.upload("http://127.0.0.1:8089")
                .add {FileDataPart(File(p), name = "file")}
                .progress { readBytes, totalBytes ->
                    progress.value = (readBytes.toFloat() / totalBytes.toFloat() * 100).toString()}
     .response { _ -> }
    }
}

在函数调用(uploadToServer())返回之前需要进度时,如何确保在应用程序线程期间更新UI?抱歉,如果已经回答了这个问题,我仍然无法确切了解这里发生的情况。

2 个答案:

答案 0 :(得分:0)

我通过以下更改解决了我的问题。我将FXTask传递给函数uploadToServer()。在这里,我带有带有HTTP POST请求的进度回调的updateMessage()。我不能说这是最好的方法,但是它可以工作。随时使用更清晰简洁的代码来更新此答案

item("_Upload") {
    isMnemonicParsing = true
    action {
        runAsync {
            controller.uploadToServer(this)
        } ui {

        }
    }
}

fun uploadToServer(task: FXTask<*>) {
    images.forEach{ p ->
        Fuel.upload("http://127.0.0.1:8089")
                .add {FileDataPart(File(p), name = "file")}
                .progress { readBytes, totalBytes ->
                    val perComplete = readBytes.toFloat() / totalBytes.toFloat() * 100
                    task.updateMessage("Uploading $p %.2f".format(perComplete).plus("%"))
                }
                .response { _ -> }
    }
}

答案 1 :(得分:0)

TornadoFX具有内置的TaskStatus对象,该对象具有用于任务进度的属性。您可以将TaskStatus对象中的一个或多个属性绑定到任何UI元素,只需在控制器函数内调用updateProgress。您甚至不需要传递TaskStatus对象,因为如果没有,将使用默认实例。

框架中有一些测试应用程序可以执行此操作:

https://github.com/edvin/tornadofx/blob/master/src/test/kotlin/tornadofx/testapps/AsyncProgressApp.kt https://github.com/edvin/tornadofx/blob/master/src/test/kotlin/tornadofx/testapps/TaskStatusTest.kt

也就是说,一种从任何其他线程更新UI的快速而肮脏的解决方案就是将UI操作代码包装在runLater {}中。例如,这对于更新标签同样有效。