2017-01-06 49 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(); 
    } 

}