2017-01-06 34 views
1

This answer提供了一个观察的列表一个解决方案,将发送“名单更新”通知如果列表变化的元素的性质。的JavaFX - ObservableList和列表的项目变化

在我的情况下,这种可观察列表的元素(一个元素类)是复杂的,我不喜欢实现每个成员变量的属性。由于这个原因,我添加到元素类 a 布尔属性表明类的变化。


元素类

import javafx.beans.property.ReadOnlyBooleanProperty; 
import javafx.beans.property.ReadOnlyBooleanWrapper; 

public class Element { 
    // ... 
    private ReadOnlyBooleanWrapper changeIndicatorWrapper; 

    public Element() { 
     //... 
     changeIndicatorWrapper = new ReadOnlyBooleanWrapper(false); 
    } 

    public ReadOnlyBooleanProperty changeIndicatorProperty() { 
     return changeIndicatorWrapper.getReadOnlyProperty(); 
    } 

    public void someMethod() { 
     // Some update 
     changeIndicatorWrapper.set(!changeIndicatorWrapper.get()); 
    } 
} 

可观察名单

ObservableList<Element> elementsObservableList = FXCollections.observableList(
    new ArrayList<>(), 
    (Element element) -> new Observable[] { element.changeIndicatorProperty() } 
); 

elementsObservableList.addListener(new ListChangeListener<Element>() { 
    @Override 
    public void onChanged(Change<? extends Element> c) { 
     System.out.println("CHANGE"); 
     while(c.next()) { 
      if (c.wasUpdated()) { 
       for (int i = c.getFrom(); i < c.getTo(); ++i) 
        System.out.println(elementsObservableList.get(i)); 
      } 
     } 
    } 
}); 

我的问题是关于这个做法。重复将changeIndicatorProperty设置为true,不触发更改事件。所以,我需要每次改变changeIndicatorProperty值changeIndicatorWrapper.set(!changeIndicatorWrapper.get())。这很奇怪,不是吗?

能否以编程方式强制更新事件?

回答

3

这很奇怪,不是吗?

不,这并不奇怪。对于要触发的更改,需要进行更改。如果BooleanProperty确定没有变化发生,因此听众没有得到任何通知,这仍然满足Property的合同。

实际上Property是不需要的。需要的是一个Observable通知它的观察员。你可以通过下面的类并调用invalidate做到这一点:

public class SimpleObservable implements Observable { 

    private final List<InvalidationListener> listeners = new LinkedList<>(); 

    @Override 
    public void addListener(InvalidationListener listener) { 
     listeners.add(listener); 
    } 

    @Override 
    public void removeListener(InvalidationListener listener) { 
     listeners.remove(listener); 
    } 

    public void invalidate() { 
     for (InvalidationListener listener : listeners) { 
      try { 
       listener.invalidated(this); 
      } catch (RuntimeException ex) { 
      } 
     } 
    } 

} 

例子:

public class Element { 

    protected final SimpleObservable observable = new SimpleObservable(); 

    public Observable getObservable() { 
     return observable; 
    } 

    public static <T extends Element> ObservableList<T> observableArrayList() { 
     return FXCollections.observableArrayList(e -> new Observable[]{e.observable}); 
    } 

    private void update() { 
     observable.invalidate(); 
    } 

    public static void main(String[] args) { 
     ObservableList<Element> list = Element.observableArrayList(); 
     list.addListener((ListChangeListener.Change<? extends Element> c) -> { 
      while (c.next()) { 
       if (c.wasUpdated()) { 
        System.out.println("update: [" + c.getFrom() + ", " + c.getTo() + ")"); 
       } 
      } 
     }); 
     list.addAll(new Element(), new Element(), new Element()); 
     list.get(1).update(); 
    } 

}