2016-11-19 9 views
1

ソースプロパティの値が変更されたときにカスタムバインディングが更新されていない大規模アプリケーションでこの問題が発生しました。JavaFXのカスタムバインディングが機能しない

私はこの問題を再現するためにシンプルなクラスを書くことができましたが、なぜこれが起こるのか分かりません。

import javafx.beans.binding.BooleanBinding; 
import javafx.beans.binding.ObjectBinding; 
import javafx.beans.property.BooleanProperty; 
import javafx.beans.property.ObjectProperty; 
import javafx.beans.property.SimpleBooleanProperty; 
import javafx.beans.property.SimpleObjectProperty; 
import javafx.beans.value.ChangeListener; 
import javafx.beans.value.ObservableValue; 

public class TestingBindingsFx { 

    private final ObjectProperty<MyEvent> objectProperty = new SimpleObjectProperty<MyEvent>(this, "objectProperty"); 
    private final BooleanProperty booleanProperty = new SimpleBooleanProperty(this, "booleanProperty"); 

    private ObjectBinding<MyEvent> bindingObj; 
    private BooleanBinding bindingBool; 

    public TestingBindingsFx(ObjectProperty<String> selection) { 
    setupBindings(selection); 
    } 

    private void setupBindings(ObjectProperty<String> selection) { 
    bindingObj = createObjectBinding(selection); 
    bindingBool = createBooleanBinding(selection); 
    objectProperty.bind(bindingObj); 
    booleanProperty.bind(bindingBool); 
    } 

    private static ObjectBinding<MyEvent> createObjectBinding(ObjectProperty<String> selection) { 
    return new ObjectBinding<MyEvent>() { 
     { 
     super.bind(selection); 
     } 

     @Override 
     protected MyEvent computeValue() { 
     System.out.println("createObjectBinding called"); 
     MyEvent ve = selection.get() == null ? MyEvent.EVENT1 
      : MyEvent.EVENT2; 
     return ve; 
     } 
    }; 
    } 

    private static BooleanBinding createBooleanBinding(ObjectProperty<String> selection) { 
    return new BooleanBinding() { 
     { 
     super.bind(selection); 
     } 

     @Override 
     protected boolean computeValue() { 
     System.out.println("createBooleanBinding called"); 
     return selection.get() == null ? true : false; 
     } 
    }; 
    } 

    public static void main(String[] args) { 
    ObjClass objclass = new ObjClass(); 
    System.out.println("Instantiating TestingBindingsFx..."); 
    TestingBindingsFx fx = new TestingBindingsFx(objclass.selection); 

    objclass.selection.addListener(new ChangeListener<String>() { 
     @Override 
     public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) { 
     System.out.println("changed " + oldValue + "->" + newValue); 
     } 
    }); 

    System.out.println("Changing selection property values..."); 
    objclass.selection.set("Test 1"); 
    objclass.selection.set("Test 2"); 
    } 

    enum MyEvent { 
    EVENT1, 
    EVENT2; 
    } 

    static class ObjClass { 
    public final ObjectProperty<String> selection = new SimpleObjectProperty<String>(this, "selection"); 
    } 
} 

だから、これを実行した後、私は以下を参照してください:ここでは、問題を複製し、簡単なテストです

Instantiating TestingBindingsFx... 
createObjectBinding called 
createBooleanBinding called 
Changing selection property values... 
changed null->Test 1 
createObjectBinding called 
createBooleanBinding called 
changed Test 1->Test 2 
createObjectBinding called 
createBooleanBinding called 
:私はのようなものを見ることが予想

Instantiating TestingBindingsFx... 
createObjectBinding called 
createBooleanBinding called 
Changing selection property values... 
changed null->Test 1 
changed Test 1->Test 2 

ChangeListenerは期待通りに動作しています(検証のためにそこに置いてください)。これはselectionプロパティの値を変更するたびに呼び出されます。

しかし、カスタムバインディングは初めて初めて更新され、コードを見るとわかりません。理由はわかりません。最初は弱い参照に関連すると思っていましたが、バインディングオブジェクトをクラスレベル変数に変更しても変更はありませんでした。

私はここで何かが欠けているかもしれないと感じますが、このコードを見て2時間後、私はなぜそれが見えません。 私の実際のアプリケーションでは、カスタムバインディングの1つが実際にうまく動作するので、さらに奇妙です。

答えて

2

これは、JavaFXが怠け者であり、真剣に考えているからです。

依存が無効にされた場合、バインディングは無効として作成され、InvalidationListenerに潜在的な変更が通知されます。 ChangeListenerを追加するか、getを使用して値を取得しない限り、computeValueメソッドは使用されません。これは、「新しい値について知りたいと思う誰もいない」ためです。これにより、パフォーマンスが向上します。

バインディングプロパティはInvalidationListenerを使用して実行され、プロパティも遅延してリフレッシュされます。

変更リスナーをプロパティに追加して、バインドが無効になるたびに値の再計算を強制します。

+0

ビンゴ、それでした!私は単純なものが欠けていることを知っていました。私はcomputeValueに集中していましたので、バインディングの遅延の性質を完全に忘れていました。再計算を強制する必要はありません。遅延は完全にうまくいきます。ソースプロパティ値を変更した後、テストコードでターゲットプロパティを読み直すだけでは足りませんでした。迅速な答えをありがとう。 – mfc

関連する問題