2016-04-30 14 views
0

私はJavaFXサービスを持っています。サービスがカスタムプロパティを更新するときにコールバックを介して通知したいと考えています。これが通常行われる方法は、サービスに "state"、 "workDone"、 "value"などのようなプロパティが組み込まれていることです。エミュレートしたいプロパティと最もよく似たものは、プロパティという名前の「値」です。 "value"プロパティは、サービスクラスで次のように定義されます。SimpleListPropertyをリッスンする<T> JavaFXサービスからの更新

// heartbeatMessageProperty listener 
// Update the GUI widgets when a new CAServiceHeartbeatMessage (heartbeatMessage) is updated 
mListenerService.heartbeatProperty().addListener(
    (ObservableValue<? extends CAServiceHeartbeatMessage> observer, 
    CAServiceHeartbeatMessage oldValue, CAServiceHeartbeatMessage newValue) -> { 
    // this is where we need to intelligently update the appropriate 
    // heartbeat service entries 
    System.out.println("updated CAServiceHeartbeatMessage"); 
}); 

// 'memberSystemMessage' bound property listener 
mListenerService.memberSystemStatusProperty().addListener(
    (ObservableValue<? extends MemberSystemStatusMessage> observer, 
    MemberSystemStatusMessage oldValue, MemberSystemStatusMessage newValue) -> { 
    if (newValue == null) { 

private final ObjectProperty<V> value = new SimpleObjectProperty<>(this, "value"); 
    @Override public final V getValue() { checkThread(); return value.get(); } 
    @Override public final ReadOnlyObjectProperty<V> valueProperty() { checkThread(); return value; } 


In my case I needed to listen to updates to a pair of message objects being updated by my JavaFX service thread, so I added a custom named property for each one as shown below. 

    // add 'heartbeat' bound property 
    private final ObjectProperty<CAServiceHeartbeatMessage> heartbeat = 
     new SimpleObjectProperty<>(this, "heartbeat", null);  
    public CAServiceHeartbeatMessage getHeartbeat() { 
     return heartbeat.get(); 
    } 
    public void setHeartbeatMessage(CAServiceHeartbeatMessage aHeartbeat) { 
     heartbeat.set(aHeartbeat); 
    } 
    public ObjectProperty<CAServiceHeartbeatMessage> heartbeatProperty() { 
     return heartbeat; 
    } 

    // add 'memberSystemStatus' bound property 
    private final ObjectProperty<MemberSystemStatusMessage> memberSystemStatus = 
     new SimpleObjectProperty<>(this, "memberStatus", null); 
    public MemberSystemStatusMessage getMemberStatus() { 
     return memberSystemStatus.get(); 
    } 
    public void setMemberSystemMessage(MemberSystemStatusMessage aMemberSystemStatus) { 
     memberSystemStatus.set(aMemberSystemStatus); 
    } 
    public ObjectProperty<MemberSystemStatusMessage> memberSystemStatusProperty() { 
     return memberSystemStatus; 
    }  

は、コントローラクラスでIは、これらの特性の各々に対する変更に基づいてGUIを更新するために、次のコードを追加しました。 。 。

私の質問は、私は、単一のSimpleListProperty Sを使用するために、複数のSimpleObjectPropertiesを交換するか、私のJavaFXのサービス・クラスでSimpleMapPropertyできるか、です。私は2つの特定の別々の名前のメッセージプロパティで行ったように、私のスレッドでいくつかの単純なリストプロパティを公開するためにいくつかのプロパティ命名規則に従う必要があるかどうか、これらのメッセージは共通の基本メッセージクラスを共有しているので、シンプルなリストタイプで保存することができます。変更が発生したときにGUIを更新できるように更新プログラムを処理する方法の例を見たいと思います。特に、リストまたはマップの要素の変更方法を知る方法がわかりません。リスト内の要素の変化に耳を傾ける

答えて

2

、あなたはFXCollectionsのこのファクトリメソッドでObservableListをinitalizeことができます。

ObservableList<Message> messages = FXCollections.observableArrayList(message -> new Observable[] { message.messageProperty() }); 

は、ArrayListのに裏打ちされた、新しい空の観察可能なリストを作成します。このリストは要素の更新を報告します。

か:

FXCollections.observableList(backingList, message -> new Observable[] { message.messageProperty() }); 

指定されたリストによって支えられてObservableListを構築します。 ObservableListインスタンスの突然変異操作は、そのインスタンスに登録されているオブザーバーに報告されます。 下位のリストに直接行われる突然変異操作は、それをラップするObservableListのオブザーバには報告されないことに注意してください。 このリストはまた、抽出器を使用して、その中の要素の変異を報告します。 (各リスト要素に適用される)エクストラクタによって返される観察可能なオブジェクトは、変更を聴取され、ListChangeListenerの「更新」変更に変換されます。詳細な回答のため

javadoc

public void changeListener() { 

     ObservableList<Message> messages = FXCollections.observableArrayList(message -> new Observable[] { message.messageProperty() }); 

     messages.addListener((ListChangeListener<Message>) c -> { 

      while (c.next()) { 
       LOGGER.debug("change: {}", c); 

       if (c.wasAdded()) { 
        List<? extends Message> addedSubList = c.getAddedSubList(); 
       } 
       if (c.wasUpdated()) { 
        int from = c.getFrom(); 
        int to = c.getTo(); 
        List<? extends Message> subList = c.getList().subList(from, to); 
       } 
      } 
     }); 

     HearBeat beat = new HearBeat("beat"); 

     messages.add(beat); 
     messages.add(new Status("status")); 

     beat.setMesssage("beat changed"); 
     beat.setMesssage("beat changed again"); 

     messages.addAll(new Status("1"), new Status("2")); 
    } 

    public abstract class Message { 

     private StringProperty message; 

     Message(String message) { 
      this.message = new SimpleStringProperty(message); 
     } 

     public StringProperty messageProperty() { 
      return message; 
     } 

     public String getMesssage() { 
      return message.get(); 
     } 

     public void setMesssage(String val) { 
      message.set(val); 
     } 
    } 

    public class HearBeat extends Message { 

     public HearBeat(String message) { 
      super(message); 
     } 
    } 

    public class Status extends Message { 

     Status(String message) { 
      super(message); 
     } 
    } 
+0

おかげで、私は、Java 8ストリームとラムダに新たなんだ - 私は実際にメッセージで何が起こっているのか理解していない - >新しい観測[] {メッセージ.messageProperty()}は奇妙な構文であり、むしろ混乱します。また、私のメッセージオブジェクトは、StringPropertyを含むように変更することはできません - 彼らは効果的にJavolutionを使用して構造体ですので、サイズを変更することはできません。どのようにあなたのサンプルをパブリッククラスに適用するのですか?MyService extends Service {...}クラスの中に私の場合ObservableArrayListにマージしたい2つのSimpleObjectPropertiesがありますか? – johnco3

+1

メッセージオブジェクト内の要素の変更をリッスンする必要がない場合は、上で示したように 'ListChangeListener'を使用できます。あなたのメッセージを、基本メッセージクラスの型式にパラメタ化された 'ObservableList'に入れ、リスナをアタッチします。'ObservableList messages = FXCollections.observableArrayList(); messages.addAll(status1、status2、beat1、beat2); messages.addListener(...); ' – jns

+1

これにより、メッセージリストに加えられた変更を見ることができます。ビートの追加、ステータスの削除はできますが、リスト要素自体に加えられた変更は表示されません。それがファクトリメソッドの抽出子が使われているものです。指定したプロパティにリスナーを関連付けます(例: messageProperty(): 'FXCollections.observableArrayList(message - > new Observable [] {m​​essage.messageProperty()})' ' – jns

関連する問題