为什么我的龙卷风FX可观察列表没有收到更新?



我有一个简单的tornadoFX程序,可以在屏幕上的随机位置生成一些圆圈。但是,没有画出任何圆圈。我添加了一些调试代码,以便在绘制圆圈时打印一条线,并且它只打印一次。

我希望圆圈以 100 毫秒的间隔出现,以及当我单击"添加演员"按钮时。

private const val WINDOW_HEIGHT = 600
private const val WINDOW_WIDTH = 1024
fun main(args: Array<String>) {
Application.launch(MainApp::class.java, *args)
}
class MainApp : App(WorldView::class, Stylesheet::class)
data class Actor(val x: Double, val y: Double)
class WorldView: View("Actor Simulator") {
override val root = VBox()
private val actors = ArrayList<Actor>(0)
init {
tornadofx.runAsync {
(0..100).forEach {
val x = ThreadLocalRandom.current().nextDouble(0.0, WINDOW_WIDTH.toDouble())
val y = ThreadLocalRandom.current().nextDouble(0.0, WINDOW_HEIGHT.toDouble())
actors.add(Actor(x, y))
Thread.sleep(100)
}
}
}
init {
with(root) {
stackpane {
group {
bindChildren(actors.observable()) {
circle {
centerX = it.x
centerY = it.y
radius = 10.0
also {
println("drew circle")
}
}
}
}
button("Add actor") {
action {
actors.add(Actor(0.0, 0.0))
}
}
}
}
}
}

奇怪的是,如果我在圆圈绘制代码期间放置断点,则会绘制圆圈并打印调试行。

一些观察:

  1. 调用someList.observable()将创建由基础列表支持的可观察列表,但基础列表上的突变不会发出事件。相反,您应该立即actors初始化为可观察列表。

  2. 对可观察列表的访问必须在 UI 线程上进行,因此您需要将突变调用包装在runLater中。

  3. 对于试图运行您的示例的人 - 您没有包含样式表,而是在App子类中引用了一个样式表,因此 IDEA 很可能会导入 TornadoFXStylesheet类。这不会有好下场:)

  4. also调用不起作用,所以我删除了它。

  5. 我在这里和那里将您的代码更新为最佳实践,例如关于如何创建根节点:)

考虑到这些要点的更新示例如下所示:

private const val WINDOW_HEIGHT = 600.0
private const val WINDOW_WIDTH = 1024.0
class MainApp : App(WorldView::class)
data class Actor(val x: Double, val y: Double)
class WorldView : View("Actor Simulator") {
private val actors = FXCollections.observableArrayList<Actor>()
override fun onDock() {
runAsync {
(0..100).forEach {
val x = ThreadLocalRandom.current().nextDouble(0.0, WINDOW_WIDTH.toDouble())
val y = ThreadLocalRandom.current().nextDouble(0.0, WINDOW_HEIGHT.toDouble())
runLater {
actors.add(Actor(x, y))
}
Thread.sleep(100)
}
}
}
override val root = stackpane {
setPrefSize(WINDOW_WIDTH, WINDOW_HEIGHT)
group {
bindChildren(actors) {
circle {
centerX = it.x
centerY = it.y
radius = 10.0
println("drew circle")
}
}
}
button("Add actor") {
action {
actors.add(Actor(0.0, 0.0))
}
}
}
}

最新更新