2017-02-22 9 views
0

ユーザ入力を取得するサブコントロールで構成されるJavaFxコントロールを作成しています。 TextField主成分は、テキストの解析された表現を表す特性を保持する。 LocalDateTime。ユーザーが何かを入力すると、このプロパティを更新する必要があります。そのため、このプロパティを子のvalueプロパティにバインドします。 valueプロパティをバインドすることで、現在の値を外部から変更することも可能である必要があります。これは、自動的に子を更新するための双方向バインディングでなければなりません。クライアントコードがプロパティにバインドされるまで、コントロールは正常に機能します。次のコードは私の問題を示しています:複数の観測値にJavaFxプロパティをバインドします。

import javafx.beans.property.SimpleIntegerProperty;

Caused by: java.lang.RuntimeException: A bound value cannot be set. 
    at javafx.beans.property.IntegerPropertyBase.set(IntegerPropertyBase.java:143) 
    at com.sun.javafx.binding.BidirectionalBinding$BidirectionalIntegerBinding.changed(BidirectionalBinding.java:467) 

私は、これは共通の問題である必要があります確信していると私はちょうど明白な解決策を見ていないです:私は、コードを実行すると、私はバウンドプロパティが設定することができないという例外を取得

public class Playbook { 

    // The internal control with a property p 
    static class Child { 
     public SimpleIntegerProperty p = new SimpleIntegerProperty(); 

     public void set(int i) {p.set(i);} 
    } 

    // My new control with a property value which is bound 
    // bidirectionally to Child.p 
    static class Parent { 
     public Child a1; 

     public SimpleIntegerProperty value = new SimpleIntegerProperty(); 

     public Parent() { 
      a1 = new Child(); 

      value.bindBidirectional(a1.p); 
     } 
    } 

    public static void main(String[] args) { 
     Parent p = new Parent(); 

     // some client code wants to keep the 
     // value updated and thus binds to it 
     SimpleIntegerProperty outside = new SimpleIntegerProperty(); 
     p.value.bind(outside); 

     // simulate a change in the child control 
     p.a1.p.set(10);   
    } 
} 

。私はReactFxを使用しているので、JavaFxまたはReactFxの任意のソリューションを歓迎します。実際のコードでは、Var.mapBidirectionalを使用してParentプロパティとChildプロパティを内部的にバインドしています。

私は何を達成したいことは以下の通りです: 1. outsideの値が変更され、これはp.valueに伝播する必要があり、その後、p.a1.pを変更した場合 2をp.a1.pする場合は、 p.valueに伝播する必要があります

これから、Parent.valueとParent.a1.pは常に同じである(マッピングに適用されるいくつかの変換情報が追加されています)と結論付けました。これには私はbidrectionalマッピングを使用します。外部は独立して変更することができ、値と異なる可能性があるため、単方向バインディングを使用します。

+2

'p.value.bind(外側);' 'p.value'は常に[値] 'と同じ値を有することを意味します。 'p.value.bindBidirectional(p.a1.p)'は、 'p.value'と' p.a1.p'が常に同じ値を持つことを意味します。明示的に、これらのルールを同時に実行することはできません。具体的には、 'p.a1.p'を' outside 'とは異なる値に明示的に設定することはできません。矛盾したルールを同時に適用しようとしているため、例外が発生しています。解決策はありません。 'int i;'を宣言し、 'i = 0'と' i = 10'を同時に作る方法を尋ねるかもしれません。 –

+0

@James_D私はその推論に従うことができるかどうかはわかりません。 Parent.valueとChild.pは常に同じ値を持つ必要があります。しかし、 'p.value.bind(outside)'(これは単方向バインディングですか?p.valueが変更されても外側に変更されていないため、値が異なる可能性があります。私はこれを外部として視覚化しようとします - >値<-> p。 – Jens

+0

これは、バインディングの意味ではありません。 'p.value.bind(outside)'は 'p.value'が* outsideに*束縛されていることを意味します。すなわち、' p.value'は常に 'outside'と同じ値を持ちます。 –

答えて

0

JavaFxバインディングが私の思うものではなく、セマンティクスがこれを許可していないことを理解した後、ReactFx'sEventStream/Val/Varに切り替えました。 ReactFxのモデルは、私は次のように動作するシステムを作成することができます私の予想に良く一致するようだ:外の値が変更された場合

  1. 、これはp.valueにし、その後p.a1.pに伝播する必要があります
  2. p.a1.pが変更された場合、これは

次のコードは、これを実装しp.valueに伝播する必要があります。これは、二重にバインドされた2つのVarを使用し、したがって、一方の変更は他方のVarに供給されます。外部からの変更はEventStreamと定義され、Varのいずれかに供給されます。

import org.reactfx.EventStream; 
import org.reactfx.EventStreams; 
import org.reactfx.value.Var; 

import javafx.beans.property.SimpleIntegerProperty; 

public class Playbook { 

    static class Child { 
     public Var<Integer> p = Var.newSimpleVar(0); 

     public void set(int i) {this.p.setValue(i);} 
    } 

    static class Parent { 
     public Child a1; 

     public Var<Integer> value = Var.newSimpleVar(0); 

     public Parent() { 
      this.a1 = new Child(); 

      this.value.bindBidirectional(this.a1.p); 
     } 
    } 

    public static void main(String[] args) { 
     Parent p = new Parent(); 

     // some client code wants to keep the 
     // value updated and thus binds to it 
     SimpleIntegerProperty outside = new SimpleIntegerProperty(); 

     // A SimpleIntegerProperty is not a Property<Integer> but a 
     // Property<Number> so we have to use map to translate to Integer 
     EventStream<Integer> stream = EventStreams.valuesOf(outside).map(Number::intValue); 

     stream.feedTo(p.value); 

     // simulate a change in the child control 
     p.a1.p.setValue(10); 
     System.out.println(p.value.getValue()); 
     System.out.println(p.a1.p.getValue()); 
     System.out.println(outside.get()); 

     // feed new value from outside 
     outside.set(42); 

     System.out.println(p.value.getValue()); 
     System.out.println(p.a1.p.getValue()); 
     System.out.println(outside.get()); 
    } 
} 

プログラムが実行され、印刷

10 
10 
0 
42 
42 
42 
関連する問題