繁体   English   中英

JavaFX 中的绑定对象

[英]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.

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