为什么JavaFX中的绑定按其工作方式起作用?

时间:2018-11-01 13:01:09

标签: java javafx data-binding kotlin

我试图理解为什么数据绑定以JavaFX中的方式工作。它使您可以像这样将ObservableValue绑定到其他ObservableValue

val prop0 = SimpleStringProperty("xul")
val prop1 = SimpleStringProperty("baz")
prop0.bind(prop1)

执行此操作时,两个属性的值都将为baz

我还可以绑定链:

val prop0 = SimpleStringProperty("xul")
val prop1 = SimpleStringProperty("baz")
val prop2 = SimpleStringProperty("qux")

prop0.bind(prop1)
prop1.bind(prop2)
// all will have the value "qux"

文档说我无法设置绑定的属性的值:

prop0.value = "foo" // exception

尽管我可以具有循环绑定:

val prop0 = SimpleStringProperty("xul")
val prop1 = SimpleStringProperty("baz")
val prop2 = SimpleStringProperty("wom")

prop0.bindBidirectional(prop1)
prop1.bindBidirectional(prop2)
prop2.bindBidirectional(prop0)

,但是简单的双向绑定将导致StackOverflowError

prop0.bindBidirectional(prop1)
prop1.bindBidirectional(prop0)

这就是为什么(我猜)有一种明确的方式进行双向绑定

val prop0 = SimpleStringProperty("xul")
val prop1 = SimpleStringProperty("baz")
val prop2 = SimpleStringProperty("wom")

prop0.bindBidirectional(prop1)
prop0.bindBidirectional(prop2)

我不明白的是为什么JavaFX将单向绑定值限制为多个其他值:

val prop0 = SimpleStringProperty("xul")
val prop1 = SimpleStringProperty("baz")
val prop2 = SimpleStringProperty("qux")

prop0.bind(prop1)
// this will unbind prop0 from prop1
prop0.bind(prop2)

但是我可以创建任意数量的BidirectionalBinding吗?当双向绑定应该是两个单向绑定时,为什么这些概念之间会有区别?

还奇怪的是,有一个Binding接口创建了一个新实体,该实体将依赖于源ObservableValue s:

val num1 = SimpleIntegerProperty(1)
val num2 = SimpleIntegerProperty(2)
// creates a new binding, which will change its value
// whenever num1 or num2 changes
val sum = num1.add(num2)

可以dispose d:

sum.dispose()

但是当我打电话给bindbindBidirectional时,它不会返回一次性Binding

我阅读了文档,但这些内容未在其中进行解释。我错过了什么?使这种行为成为必需的内部逻辑是什么?

1 个答案:

答案 0 :(得分:1)

a的绑定属性b意味着只要绑定就位,a的值始终与值b的值相同。除了将a绑定到cb上,还需要a的值与bc相同,但是它们可以包含不同的值。因此,仅允许单个绑定。取消绑定属性会自动处理“处置”。

双向绑定会导致两个属性的值保持相同。更改一个会更新另一个,因此您可以将一个属性绑定到任意数量的属性中。如果更改属性,则双向绑定到该属性的所有其他属性都会更新,并且更改其他属性之一会更新属性本身,从而也会更新所有其他属性。没问题。
JavaFX选择了解除双向绑定的另一种方式:

a.bindBidirectional(b);
...
a.unbindBidirectional(b);

这负责“处置”。

与属性之间的绑定相反,绑定对象是ObservableValue对象,它们依赖于某些Observable。绑定对象自动向其依赖项注册InvalidationListener,但是由于不再使用绑定对象,因此依赖项无法知道可以删除此侦听器。这就是为什么绑定对象允许您通过不再使用它的dispose方法来进行“清理”的原因。