繁体   English   中英

TornadoFx的UI中为什么会自动添加root后声明的变量?

[英]Why are variables declared after root automatically added to UI in TornadoFx?

我偶然发现了 TornadoFx 中似乎没有在任何地方提及的行为(我已经搜索了很多)并且我想知道。

如果我使用 TornadoFx 构建器为标签定义这样的视图:

class ExampleView: View() {

    override
    val root = vbox{ label("first label") }

    val secondLabel = label("second label")
}

结果是:

在此处输入图像描述

也就是说,仅secondLabel的定义就会自动将其添加到场景的root中。

但是,如果我将此定义放在root的定义之前...

class ExampleView: View() {

    val secondLabel = Label("second label")

    override
    val root = vbox{ label("first label") }
}

...或者如果我使用 JavaFx Label class 而不是 TornadoFx 构建器...

class ExampleView: View() {

    override
    val root = vbox{ label("first label") }

    val secondLabel = Label("second label")
}

...然后它按我的预期工作:

在此处输入图像描述

当然,我可以在定义root元素之前简单地定义视图中的所有变量,但我仍然很好奇为什么会存在这种行为; 也许我错过了一些一般的设计规则或设置。

TornadoFX 中的构建器自动将自己附加到 scope 中的当前父级,它们被调用。因此,如果您在视图本身上调用构建器 function,生成的 ui 组件将自动添加到该视图的根目录。 这就是你所看到的。

如果您确实有一个有效的用例来创建应包含在层次结构之外的 ui 组件,则不应调用构建器 function,而是使用其构造函数实例化元素,就像您使用Label()所做的那样。 但是,这种行为的用例很少。

最佳实践是将值属性存储在视图或视图 model 中,并使用构建器将属性绑定到 ui 元素。 然后在需要时操作 value 属性,更改将在 ui 中自动更新。 因此,您很少需要在稍后阶段访问特定的 ui 元素。 例子:

val myProperty = SimpleStringProperty("Hello world")

override val root = hbox {
    label(myProperty)
}

当您想要更改 label 值时,只需更新属性即可。 (该属性应该在实际应用程序中的注入视图 model 中)。

如果确实需要对 ui 元素进行引用,则应先声明 ui 属性,然后在实际构建 ui 元素时为其赋值。 使用singleAssign()委托定义 ui 属性,以确保您只分配给它一次。

var myLabel: Label by singleAssign()

override val root = hbox {
    label("My label) {
        myLabel = this
    }
}

我想再次强调,这是很少需要的,如果你觉得你需要它,你应该重新构建你的 ui 代码,使其更多地由数据驱动。

另一种避免存储对 ui 元素的引用的技术是利用 EventBus 来监听事件。 有很多这样的例子。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM