繁体   English   中英

JavaFX强制重新计算绑定

[英]JavaFX force recompute binding

我想在JavaFX中实现类似功能反应式编程的东西,我认为既然JavaFX已经支持属性之间的监听器和绑定,那么它应该相当容易,所以我创建了用于转换绑定的小框架,例如我现在可以做类似的事情了这个(Scala中的例子,但应该可以理解我的意思):

val property1: Property[String]
val property2: Property[Path]

Bindings.Conversions
    .bindUni(property1).to(property2)
    .using(p => p.getFileName.toString)
    .connect()

在这里,我通过转换函数绑定property2值(这是一个java.nio.file.Path ),该转换函数获取路径的最后部分并将字符串转换为property1 (字符串)。

这个实现非常简单(即使对于双向绑定;我只是从openjfx BidirectionalBinding类中获取一些代码,将其转换为Scala并将其调整为转换),我想知道为什么JavaFX中已经没有这样的东西了。

这一切都运行良好,我甚至可以创建这种绑定的复杂链。 除非转换功能取决于某些外部状态,否则一切正常。

例如,假设您有以下绑定链:

Text field value  -1->  intermediate java.nio.file.Path  -2->  another String  -->  Label

当文本字段更改时,将自动重新计算PathString ,并将String属性的值写入标签。 一切都很棒。 但是假设-2->转换应该依赖于某些复选框的切换状态:

                                       Checkbox state  ---+
                                                          |
Text field value  -1->  intermediate java.nio.file.Path  -2->  another String  -->  Label

也就是说,当选中复选框时,转换应略有不同。

显然,直接实现这种结构是行不通的,因为更改复选框状态不会切换转换链的重新计算。 但是,我发现JavaFX没有提供任何强制更改事件的方法。 我尝试重写SimpleStringProperty ,例如,暴露它的fireValueChangedEvent()方法,但这没有帮助。 目前我正在做类似textField.setText(""); textField.setText(oldValue);事情textField.setText(""); textField.setText(oldValue); textField.setText(""); textField.setText(oldValue); 但是这是非常丑陋的,是不正确的做法,效果显着。

我错过了什么,我真的可以做我想做的事,或者根本就没有这样的东西,我完全搞砸了?

如果答案是否定的,那么我认为这严重损害了整个框架的表达能力。 我知道我真的可以和很多听众一起做我想做的事情,但这很丑陋,我希望尽可能地让整个事情变得一般。

您可以像收听String属性一样收听CheckBox#selectedProperty() 见下一个例子:

public class ConditionalBind extends Application {

    Label label = new Label();
    TextField tf = new TextField("hi");
    CheckBox cb = new CheckBox("lowerize");

    @Override
    public void start(Stage primaryStage) {

        label.textProperty().bind(new StringBinding() {

            {
                bind(tf.textProperty(), cb.selectedProperty());
            }

            @Override
            protected String computeValue() {
                return cb.isSelected() ? tf.getText().toLowerCase() : tf.getText();
            }
        });

        VBox root = new VBox(10);
        root.getChildren().addAll(label, cb, tf);
        primaryStage.setScene(new Scene(root, 300, 250));
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

正如“丑陋”的解决方法一样,我最终随意改变了值而没有改变含义。 例如,对于一个双值,我会添加一个小的随机量来强制改变或一个字符串值我切换和不可见的空间。 这一切都不好,但会获得触发属性更改的效果。

在多线程环境中情况变得更糟。 在那里,如果绑定恰好在属性的初始设置之后稍微发生,则可能发生有界属性不会获得更改触发器。 如果现在将属性设置为相同的值,则该值将被视为未更改,并且有界属性将不会获取初始值,而是保持为null或default值。 十分难看!

暂无
暂无

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

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