将 属性 绑定到从 JavaFx / TornadoFX 中的控件派生的值的正确方法

Proper way to bind a Property to a Value derived from a control in JavaFx / TornadoFX

考虑下面的 (kotlin/tornadofx) 示例,该示例旨在通过绑定将文本字段的内容与标签的文本连接起来。标签应反映文本字段的派生值,在本例中为散列。我该如何正确实现这种绑定(我觉得使用 changelistener 不是正确的方法)。

class HashView : View("My View") {
    val hashProperty = SimpleStringProperty("EMPTY")

    override val root = vbox {
        textfield {
            hashProperty.bind(stringBinding(text) { computeHash(text)}) // This does not work
        }
        label(hashProperty)
    }
}

PS:也欢迎在 java/JavaFX 中回答,只要我能以某种方式将这个想法也应用到 tornadofx 中。

更新 1:我发现只需要做一个小改动就可以使我的示例正常工作,即它应该是

hashProperty.bind(stringBinding(textProperty() { computeHash(this.value) })

但是我仍然不确定这是否是常规方法。所以我打算让这个问题悬而未决。

在 JavaFX 中,您可以使用 StringConverter:

    TextField field = new TextField();
    Label label = new Label();

    label.textProperty().bindBidirectional(field.textProperty(), new StringConverter<String>() {

        @Override
        public String toString(String fieldValue) {

            // Here you can compute the hash
            return "hash(" + fieldValue+ ")";
        }

        @Override
        public String fromString(String string) {

            return null;
        }

    });

我建议不要在计算中涉及实际输入元素的属性。您应该首先定义输入 属性 并将其绑定到文本字段。然后创建派生的 StringBinding 并将其绑定到标签。另请注意,属性 具有内置的 stringBinding 函数,可自动在 属性 上运行。这使您的代码看起来更简洁,可以在需要时重用并且更易于维护:

class HashView : View("My View") {
    val inputProperty = SimpleStringProperty()
    val hashProperty = inputProperty.stringBinding { computeHash(it ?: "EMPTY") }

    override val root = vbox {
        textfield(inputProperty)
        label(hashProperty)
    }

    fun computeHash(t: String) = "Computed: $t"
}