javafx 双向绑定不同步

问题描述 投票:0回答:1

我正在 javafx 中编写一个类,其中有两个双向绑定的属性,并且正在测试一些边缘情况。我发现,如果您从失效侦听器内部更改其中一个属性的值,则会导致属性不同步。这是一个小例子:

static class A {
    IntegerProperty x = new SimpleIntegerProperty(this, "x", 0);
    IntegerProperty y = new SimpleIntegerProperty(this, "y", 0);
    A() {
        x.bindBidirectional(y);
    }
}

static void testA() {
    A a = new A();
    a.x.addListener( o -> { //InvalidationListener
        if (a.x.get() < 0) a.x.set(0);
    });
    // after y is set to a negative value, x and y hold different values
    // until either y is set to a value that's >= 0 or x is set to any value
    a.y.set(-2);
    System.out.println(a.x.get());
    System.out.println(a.y.get());
}

输出:

0
-2

我假设在使用双向绑定时,更改一个属性总是会导致另一个属性被更新。人们似乎很少(而且可能是不明智的)编写这样的失效侦听器,但我在这里防御性地思考。如果这些属性至少有一个被暴露,我不希望它能够破坏我的类的任何不变量。我想这里有三种可能的解释:

  1. 双向绑定的契约并不意味着它们总是同步的(要么它们保持相同的值,要么它们被标记为无效),它只是在尽力而为的基础上。因此,类不变量不应该基于这个事实。

  2. 更改失效侦听器内的值会破坏双向绑定的前提条件,应避免。否则它们总是同步的。因此,您可以基于这个事实创建一个类不变量,因为要求客户端不应该编写这样的失效侦听器是合理的。

  3. 这是一个错误,无论如何,它们确实是同步的。我想如果这是真的,那么您可以轻松地生成更改通知的无限循环(例如向 y 添加一个始终将值设置为 < 0). So, it would be up to the client to prevent such cases.

    的失效侦听器)

这些解释是否接近事实,还是我在这里遗漏了其他内容?另外,我很想知道是否存在其他类型的绑定操作考虑到这些情况。

java javafx properties
1个回答
0
投票

我认为你的第二个理论是正确的:

更改失效侦听器内的值会破坏双向绑定的前提条件,应避免。否则它们总是同步的。因此,您可以基于这个事实创建一个类不变量,因为要求客户端不应该编写这样的失效侦听器是合理的。

双向绑定操作

要了解双向绑定操作,您可以查看源代码。

例如参见TypedNumberBidirectionBinding。它有一个标志

updating
,用于设置并检查属性何时无效。如果在失效侦听器内再次更新属性,则更新标志将为 true,并且将跳过属性值的同步。

(出于示例目的,简化了失效代码)。

if (!updating) {
    updating = true;
    try {
        if (property1 == sourceProperty) {
            T newValue = property1.getValue();
            property2.setValue(newValue);
            property2.getValue();
            oldValue = newValue;
        } else {
            T newValue = (T)property2.getValue();
            property1.setValue(newValue);
            property1.getValue();
            oldValue = newValue;
        }
    } finally {
        updating = false;
    }
}

推荐

InvalidationListener javadoc 指出:

一般来说,在此方法中修改观测值被认为是不好的做法。

因此,我建议您不要“从失效侦听器内部更改其中一个属性的值”。

滑盖盒

滑块类中 valueProperty 的双向绑定在超出范围时将无法正确同步

这是因为 Slider 类做了不推荐的事情。它修改失效监听器中滑块值属性的值

修改是将变化值钳制在滑块范围内。

这会导致 Slider 类中 valueProperty 的双向绑定在越界时无法正确同步。

滑块文档指出

该值必须始终介于最小值和最大值之间(含边界值)。如果由于最小或最大更改或由于自身更改而超出范围,则它将被限制以始终保持有效。

© www.soinside.com 2019 - 2024. All rights reserved.