从JavaFX服务中侦听SimpleListProperty <t>更新

时间:2016-04-30 19:37:25

标签: java javafx javafx-2 observable

我有一个JavaFX服务,我希望在服务更新自定义属性时通过回调通知我。通常,这样做的方法是服务有一些内置的属性,如&#34; state&#34;,&#34; workDone&#34;,&#34; value&#34;与我想要模仿的那个最相似的是&#34;值&#34;命名财产。 &#34;值&#34; property在服务类中定义如下。

    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;
    }    

然后在Controller类中,我添加了以下代码,以根据对每个属性的更改来更新GUI:

// 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) {

。 。

我的问题是,如何在我的JavaFX服务类中替换多个SimpleObjectProperties以使用单个SimpleListPropertySimpleMapProperty。我不确定如何,或者我是否需要遵循一些属性命名约定来在我的线程中公开一些简单的列表属性,就像我对2个特定和单独命名的消息属性所做的那样。值得注意的是,这些消息共享一个公共基本消息类 - 因此它们可以存储在一个简单的列表类型中。我还想看一个如何处理更新的示例,以便我可以在发生更改时更新GUI,特别是我不知道如何确定列表或地图中的哪些元素发生了变化。

1 个答案:

答案 0 :(得分:2)

要收听列表中元素的更改,您可以使用ObservableList的工厂方法初始化FXCollections

 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);
        }
    }