2013-06-11 17 views
5

JavaFXで機能的なリアクティブプログラミングに似た何かを実現したいと思っていましたが、JavaFXはすでにプロパティ間のリスナーとバインディングをサポートしているので、かなり簡単にできると思っていました。私は今、このような何かをすることができています(スカラ座の例が、私が何を意味するかを理解することが可能なはずである):ここではJavaFX強制バインドを再作成する

val property1: Property[String] 
val property2: Property[Path] 

Bindings.Conversions 
    .bindUni(property1).to(property2) 
    .using(p => p.getFileName.toString) 
    .connect() 

私は、変換関数を介して(java.nio.file.Pathです)property2の値を結合しますパスの最後の部分をとり、文字列に変換してproperty1(文字列)にします。

これの実装は本当にシンプルです(双方向バインディングの場合でも、openjfx BidirectionalBindingクラスからいくつかのコードを取り出し、それをScalaに変換して変換に適合させました)、なぜJavaFXにこのようなことはないのでしょうか? 。

これはすべてうまく動作し、このようなバインディングの複雑なチェーンを作成することもできます。変換機能が外部状態に依存しない限り、すべては正常です。

と仮定は、例えば、あなたがバインディングの以下のチェーンがあること:

Text field value -1-> intermediate java.nio.file.Path -2-> another String --> Label 

テキストフィールドの変更を、PathStringが自動的に再計算され、Stringプロパティの値は、ラベルに書かれています。すべて素晴らしいです。しかし-2->変換は、いくつかのチェックボックスの切り替え状態に依存しなければならないこととします

         Checkbox state ---+ 
                  | 
Text field value -1-> intermediate java.nio.file.Path -2-> another String --> Label 

チェックボックスがチェックされている場合、変換がわずかに異なるべきである、すなわち。

チェックボックス状態の変更が変換チェーンの再計算を切り替えないので、このような構造の直接的な実装は、明らかに機能しません。しかし、私は、JavaFXが変更イベントを強制する手段を提供していないことを発見しました。たとえば、SimpleStringPropertyを無効にして、そのfireValueChangedEvent()メソッドを公開しようとしましたが、これは役に立ちませんでした。現在、私はtextField.setText(""); textField.setText(oldValue);のようなことをしていますが、これは非常にですが、明らかに正しい方法ではありません。

私は何かを見逃していますか、私がやりたいことをすることは本当に可能ですか、そういったことは全くありません。私は完全にここに釘付けになっていますか?

答えがノーならば、これはフレームワーク全体の表現力を大きく損なうものだと思います。私は本当に多くのリスナーと一緒に私がしたいことをすることができることを理解していますが、これは醜いでしょう、私は可能な限り一般的なものにしたいです。

答えて

1

CheckBox#selectedProperty()は、ストリングのプロパティーを聞くのと同じ方法で聞くことができます。私はランダムに意味を変えずに値を変更することになった「醜い」の回避策としてとして

public class ConditionalBind extends Application { 

    Label label = new Label(); 
    TextField tf = new TextField("hi"); 
    CheckBox cb = new CheckBox("lowerize"); 

    @Override 
    public void start(Stage primaryStage) { 

     label.textProperty().bind(new StringBinding() { 

      { 
       bind(tf.textProperty(), cb.selectedProperty()); 
      } 

      @Override 
      protected String computeValue() { 
       return cb.isSelected() ? tf.getText().toLowerCase() : tf.getText(); 
      } 
     }); 

     VBox root = new VBox(10); 
     root.getChildren().addAll(label, cb, tf); 
     primaryStage.setScene(new Scene(root, 300, 250)); 
     primaryStage.show(); 
    } 

    public static void main(String[] args) { 
     launch(args); 
    } 
} 
+0

これも私が見つけたものですが、現在は低レベルのバインディングを使用して同様のアプローチを使用しています。しかし、このアプローチは、変換を伴う双方向バインディングにはあまり適していないようです。これは私のユースケースでは問題ではありませんが、フレームワークにとって問題であると思います。私はあなたの答えを受け入れます、これは本質的に私が今使っているものなので。ありがとうございました。 –

+0

偉大なあなたのケースが解決されます。フレームワークの問題に関しては、javafx-jira.kenai.comで問題を提出したり、[email protected]にメールを書いたりすることをお勧めします。この方法で直接開発者と連絡を取ることができます。 –

0

:次の例を参照してください。例えば。二重値の場合は、強制的に小さなランダムな量を加えたり、文字列の値をトグルして見えない空間に追加したりします。それはすべていいものではありませんが、始めにプロパティの変更をトリガーする効果があります。

マルチスレッド環境では状況が悪化します。バインディングがプロパティーの初期設定の少し後に行われた場合、バインドされたプロパティーは変更トリガーを取得しません。プロパティを同じ値に設定すると、値は変更されていないとみなされ、バインドされたプロパティは初期値を取得せず、null値またはデフォルト値のままになります。非常に醜い!

関連する問題