2017-02-07 6 views
2

複雑なオブジェクトを必要なデータで参照する複数のJavaFXペインとキャンバスがあり、オブジェクトが変更されたときに再描画するようにしたい。複雑なオブジェクトをObservableにする方法

これはオブジェクトが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

「Can not swap」は、同じ「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

ありがとう!単純化された形で推測すると、ブールを使用してリスナーに警告し、実際の値に対しては正規のintとアクセサを使用します。質問:1.これは、変更があるたびにブールを切り替える必要があることを意味しますか? IIRCリスナは、データが実際に変更されたときにのみトリガします。 2.これは、システムをハッキングして、自分の望むことをするような感じです。無効化リスナーを処理する一般的な方法ですか? – EboMike

+0

@EboMike技術的には、ObservableValue'ライブラリなしですべてを実装することができます。その場合は、手作業で独自のgetter/setterを作成し、setterでbooleanフィールドをtrueに変更する必要があります。あなたが私の答えに従っているなら、バインディング(this.internalChanged.bind(Bindings.createBooleanBinding(() - > this.internalChanged.set(true)、this。value1、this.value2));))あなたのためにそれを処理する必要があります。もちろん、これにすべてのプロパティを追加する必要があります。内部的には、すべてのプロパティのchangelistenerにサブスクライブする 'Bindings.createBooleanBinding()'と想像することができます。 – Jai

+0

私はそれをして、それは働いた! (まあ、真に設定するのではなく、ブール値をトグルしますが、同じことです)。私はまだ私がシステムを完全に乱用しているように感じますが、それは機能するので、私はどれだけ気にするべきか分かりません。ありがとうございました! – EboMike

0

インターフェイスObjectPropertyBase<T>ObjectPropertyBase<T>と​​があり、Observableを実装していますか。

ただし、オブジェクトが変更され、ロジックをリスニングするタイミングを定義する必要があります。

申し訳ありませんが、それは単なる仕事の痕跡ですが、役に立つと思います。

+0

ありがとう!はい、私はそれらを見ました。しかし、これらもObservableValueを実装しています。これは私の質問で言及したものと同じです。オブジェクトをラップするので、ラッパー内のオブジェクト自体を置き換えて何かが変わった。 – EboMike

関連する問題