Java 如何使复杂对象成为可观察对象

Java 如何使复杂对象成为可观察对象,java,javafx,observable,Java,Javafx,Observable,我有多个JavaFX窗格和画布,这些窗格和画布引用了一个复杂对象及其所需的数据,我希望它们在对象更改时重新绘制 这将要求对象是可观察的,但我应该使用哪个类?JavaFX似乎大部分都有ObservalEvalue子类,它们包装一个值并允许将其交换出去。我不想交换复杂的对象,只是在发生更改时通知侦听器。我可以通过实现addListener来做到这一点,但我确信已经有一个子类为我做到了这一点 class ComplexObject /* extends SomeObservableClass */ {

我有多个JavaFX窗格和画布,这些窗格和画布引用了一个复杂对象及其所需的数据,我希望它们在对象更改时重新绘制

这将要求对象是可观察的,但我应该使用哪个类?JavaFX似乎大部分都有ObservalEvalue子类,它们包装一个值并允许将其交换出去。我不想交换复杂的对象,只是在发生更改时通知侦听器。我可以通过实现
addListener
来做到这一点,但我确信已经有一个子类为我做到了这一点

class ComplexObject /* extends SomeObservableClass */ {
    public int getValue1 { complex calculations... };
    public int getValue2 { ... };

    public void setNewValue1(int newValue) { ... }
}

class ComplexRenderer extends Canvas implements InvalidationListener {
    private ComplexObject complexObject;

    public void setComplexObject(ComplexObject complexObject) {
        this.complexObject = complexObject;
        complexObject.addListener(this);
    }

    public void draw() { ... }
}
ComplexObject应该扩展哪个类?是否有什么东西可以维护侦听器列表,并具有类似fireValueChangedEvent()的内容,以便我可以让它通知所有侦听器


我在JavaFX中看到的一切似乎都是针对属性的,而属性在这里似乎不是正确的选择。

也许你可以看看接口
ObjectPropertyBase
和类
ObjectPropertyBase
SimpleObjectProperty
,它们实现了
Observable

但是,您必须定义对象更改的时间和侦听逻辑


很抱歉,这只是工作的一点痕迹,但我希望它可能有用。

不太清楚你所说的交换是什么意思,也不太确定我是否正确理解你

class ComplexObject {
    private IntegerProperty value1 = new SimpleIntegerProperty();
    private IntegerProperty value2 = new SimpleIntegerProperty();
    private BooleanProperty internalChanged = new SimpleBooleanProperty(false);

    public ComplexObject() {
        this.internalChanged.bind(Bindings.createBooleanBinding(() ->
            this.internalChanged.set(!this.internalChanged.get()), this.value1, this.value2));
    }

    public IntegerProperty value1Property() { return this.value1; }
    public int getValue1() { return this.value1.get(); }
    public void setValue1(int value) { return this.value1.set(value); }

    public IntegerProperty value2Property() { return this.value2; }
    public int getValue2() { return this.value2.get(); }
    public void setValue2(int value) { return this.value2.set(value); }

    public void setNewValue1(int newValue) { /* What value is this??? */ }

    public BooleanProperty internalChangedProperty() { return this.internalChanged; }
}

class ComplexRenderer extends Canvas implements InvalidationListener {
    private ComplexObject complexObject;

    public void setComplexObject(ComplexObject complexObject) {
        this.complexObject = complexObject;
        complexObject.internalChangedProperty().addListener(this);
    }
    @Override public void invalidated(Observable observable) {
        // Something inside complex object changed
    }

    public void draw() { ... }
}

谢谢是的,我看过了。然而,它们也实现了
ObservableValue
,这与我在问题中提到的一致——它们包装了一个对象,因此我的理解是,您需要在包装器中替换对象本身,以表明发生了变化。我不太清楚“无法交换”是什么意思我不确定您是指交换整个
ComplexObject
还是其中的一些值。是否仅在调用时才需要对
getValue()
进行计算?或者在调用之前可以计算和存储它吗?“不能交换”意味着我想保持相同的
ComplexObject
,只需更改其中的值即可。在我看来,
ObjectPropertyBase
及其朋友被设计成包装器,因此您可以通过
set()
替换整个对象,然后将触发失效侦听器。我可以存储复杂的计算并将结果作为单独的属性公开,但最初的目的是让复杂的对象按需进行计算。这意味着我的答案应该接近您所寻找的。您不跟踪
ComplexObject
reference中的更改。而是跟踪其内部值(要装箱的基本体)和对象的引用的更改。如果需要跟踪单个属性,则需要向它们添加单个侦听器。否则,您可以公开一个
BooleanProperty
,以侦听任何属性中的任何更改。当然,在内部,您需要将这些属性绑定到
BooleanProperty
。谢谢!我想在一个简化的形式中,我将使用bool来提醒侦听器,并使用常规int和访问器来获取实际值。问题:1。这是否意味着每次有变化时我都需要切换布尔值?IIRC侦听器仅在数据实际更改时触发。2.这似乎有点像黑客入侵系统,让它做我想要的。这是处理无效侦听器的常用方法吗?@EboMike从技术上讲,您可以在不使用
observeValue
库的情况下实现所有功能。在这种情况下,您需要手动编写自己的getter/setter,并使setter将布尔字段更改为true。如果您遵循我的答案,那么绑定(
this.internalChanged.bind(Bindings.createBooleanBinding(()->this.internalChanged.set(true)、this.value1、this.value2));
)应该可以为您处理它。当然,您需要将所有属性都添加到此中。在内部,您可以想象为
Bindings.createBooleanBinding()
订阅所有属性的changelistener。我做到了,它成功了!(好吧,我正在切换布尔值,而不仅仅是将其设置为true,但事情是一样的)。我仍然觉得我完全是在滥用这个系统,但它是有效的,所以我不知道我应该有多在乎。非常感谢。