[英]Binding objects in JavaFX
我很困惑如何使用 Object 綁定將 ObjectProperty 綁定到另一個 Object 。 根據我在 javaFX 文檔中的閱讀和理解,這個 MCVE 應該是 output 20,但它不起作用。 Output 即將為 0。
// I tried to bind the attribute B's Integer attribute in class A to class C's SimpleIntegerProperty
package sample;
import javafx.beans.binding.ObjectBinding;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleObjectProperty;
class ObjectBindingImpl extends ObjectBinding {
private A a;
public ObjectBindingImpl(A a) {
this.a = a;
bind(new SimpleObjectProperty<>(a.b));
}
@Override
protected Object computeValue() {
return a.b == null ? null : a.b.b;
}
}
public class Main {
public static void main(String[] args) {
A a = new A();
C c = new C();
c.c.bind(new ObjectBindingImpl(a));
a.b = new B(20); // Clearly I change the value to 20 here
System.out.println(c.c.get()); // Expected output 20 as B.b = 20 but output returned is 10.
}
}
class A {
B b = new B(10); // Assigned it value 10.
}
class B {
Integer b;
B(int b) {
this.b = b;
}
}
class C {
SimpleIntegerProperty c = new SimpleIntegerProperty();
}
根據我的理解,由於我調用了 bind(new SimpleObjectProperty(ab)) 所以每次 ab 的值發生變化時,綁定就會失效,然后某個時候,它使用 computeValue() 方法 impl 為其分配更新的值。
但似乎無論分配給它的第一個值是什么,即使在更改數據之后也不會改變。 我在這里想念什么? 我怎樣才能使這個相同的例子工作?
您的代碼中的問題是,您不更改屬性,而只更改基礎數據。 為了使 Property-Bindings 識別您的更改,您需要設置屬性:
A a = new A();
SimpleObjectProperty aProperty = new SimpleObjectProperty<>(a);
SimpleObjectProperty bProperty = new SimpleObjectProperty<>(a.b);
System.out.println(aProperty.get()); // A, because we set it to a.
aProperty.bind(bProperty);
System.out.println(aProperty.get()); // null, because a.b is null (and we bound the value from bProperty now)
bProperty.set(new B()); // Set the bProperty. This will update the aProperty as well, because it is bound to bProperty
System.out.println(aProperty.get());
// B, because we set bProperty to B, and as aProperty is bound to bProperty, this will change aProperty to it as well.
這也在所有 JavaFX 控件中完成。 看看例如TableView
:
private ObjectProperty<ObservableList<S>> items = new SimpleObjectProperty<ObservableList<S>>(this, "items");
public final ObjectProperty<ObservableList<S>> itemsProperty() { return items; }
public final void setItems(ObservableList<S> value) { itemsProperty().set(value); }
public final ObservableList<S> getItems() {return items.get(); }
所以每個 setter 都會設置屬性。 然后,您可以將該屬性綁定到另一個屬性(或使用addListener
添加一個偵聽器以對更改做出反應)。
我的解釋或多或少類似於@Maran23。 您可以使綁定僅在可觀察屬性之間起作用。
在您提供的示例中,綁定在 C.c 和綁定 class 中的“新 SimpleObjectProperty”實例之間。
您正在更新 ab 值,這不是可觀察的屬性。
要獲得 C.c 中反映的值,應更新“new SimpleObjectProperty”中的值。 這在您的示例中是不可能的,因為該實例是動態創建的,並且沒有更新它的參考。
因此,要使您的示例正常工作,請為您在 ObjectBindingImpl 中創建的可觀察屬性創建一個引用,並確保更新此可觀察屬性值。
我還想糾正你的一個假設
“ ...然后一段時間后,它使用 computeValue() 方法 impl 為其分配更新的值”
它不會在某個隨機時間更新。 僅當您顯式調用可觀察屬性的“get”方法時,它才會調用 computeValue。 在調用 getter 之前,可觀察屬性將處於“無效”state 中。
請在下面的演示中找到我提到的更改。 另請注意,還有許多其他有效的方法可以讓綁定發生,但我試圖用您提供的示例來回答您的實際操作。
import javafx.beans.binding.ObjectBinding;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleObjectProperty;
public class ObjectBinding_Demo {
public static void main(String[] args) {
new ObjectBinding_Demo().init();
}
private void init() {
A a = new A();
C c = new C();
ObjectBindingImpl binding = new ObjectBindingImpl(a);
c.c.bind(binding);
a.b = new B(20);
binding.obj.setValue(a.b); // Update the observable property with the new value
System.out.println("Value set in binding observable property..");
System.out.println(c.c); // Output:: IntegerProperty [bound, invalid]
System.out.println(c.c.get()); // Output:: 'Computing value...' string and then 20
System.out.println(c.c); // Output:: IntegerProperty [bound, value: 20]
}
class ObjectBindingImpl extends ObjectBinding {
private A a;
ObjectProperty obj; // Observable property reference for future updating.
public ObjectBindingImpl(A a) {
this.a = a;
obj = new SimpleObjectProperty(a.b);
bind(obj);
}
@Override
protected Object computeValue() {
System.out.println("Computing value...");
return a.b == null ? null : a.b.b;
}
}
class A {
B b = new B(10); // Assigned it value 10.
}
class B {
Integer b;
B(int b) {
this.b = b;
}
}
class C {
SimpleIntegerProperty c = new SimpleIntegerProperty();
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.