2017-02-07 39 views
2

我有多個JavaFX窗格和畫布引用一個複雜對象與他們需要的數據,我希望它們在對象更改時重繪。如何製作一個複雜的對象Observable

這將要求對象是可觀察的,但是我使用哪個類? JavaFX似乎主要有ObservableValue子類,它們包裝一個值並允許將其交換出去。我不想換出複雜的對象,只是在發生更改時通知監聽者。我可以通過執行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中看到的一切似乎都是針對屬性的,在這裏看起來並不是正確的選擇。

+0

不太確定你的意思是「不能交換」。我不確定你是否想要交換整個'ComplexObject'或者其中的一些值。你是否需要僅在調用getValue()時進行計算?或者可以在被調用之前進行計算和存儲? – Jai

+0

「不能交換」意味着我想保持相同的'ComplexObject',只是改變其中的值。在我看來,'ObjectPropertyBase'及其朋友被設計成包裝器,所以你通過'set()'替換整個對象,然後它將觸發失效偵聽器。我可以存儲複雜的計算結果並將結果作爲單獨的屬性公開,但最初的目的是僅僅擁有複雜的對象並根據需要進行計算。 – EboMike

+0

這意味着我的答案應該接近你正在尋找的東西。您不會跟蹤'ComplexObject'參考中的更改。而是跟蹤其內部值(基元將被裝箱)和對象的引用的更改。如果您需要跟蹤個人財產,則需要爲其添加個人監聽者。否則,您可以公開一個'BooleanProperty',您可以偵聽任何屬性中的任何更改。當然,在內部,您需要將這些屬性綁定到'BooleanProperty'。 – Jai

回答

3

不太清楚你換了什麼意思,而且不確定我是否理解你的意思。

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() { ... } 
} 
+0

謝謝!我想以簡化的形式,我將使用bool來提醒監聽器,並使用常規整數和訪問器來獲取實際值。問題:1.這是否意味着每次發生變化時都需要切換布爾值? IIRC監聽器只在數據實際發生變化時觸發。這看起來有點像黑客攻擊系統,讓它做我想做的事。這是處理無效偵聽器的普遍方式嗎? – EboMike

+0

@EboMike那麼,從技術上講,你可以在沒有'ObservableValue'庫的情況下實現一切。在這種情況下,您需要手動編寫您自己的getters/setters,並讓setter將boolean字段更改爲true。如果你按照我的回答,綁定('this.internalChanged.bind(Bindings.createBooleanBinding(() - > this.internalChanged.set(true))。value1,this.value2));')應該爲你處理它。當然,你需要添加所有的屬性。在內部,你可以想象爲'Bindings.createBooleanBinding()'訂閱changelistener的所有屬性。 – Jai

+0

我做到了,它工作! (好吧,我正在切換布爾值而不是將它設置爲true,但是同樣的事情)。我仍然覺得我完全濫用這個系統,但它有效,所以我不知道我應該關心多少。謝謝! – EboMike

0

也許你可以看看接口ObjectPropertyBase<T>和類ObjectPropertyBase<T>和​​其實施Observable

但是,您必須定義對象何時更改和偵聽邏輯。

對不起,這只是一絲工作,但我希望它可能有用。

+0

謝謝!是的,我看着那些。然而,這些也實現了'ObservableValue',它符合我在我的問題中提到的那些 - 它們包裝一個對象,所以我的理解是,你期望在包裝器中替換對象本身以指示某些變化。 – EboMike

相關問題