2017-01-06 4 views
1

This answer bietet eine Lösung für eine beobachtbaren Liste der „Liste aktualisiert“Benachrichtigungen wenn Eigenschaften von Elementen der Liste Änderung senden.JavaFX - ObservableList und Artikelliste Änderung

In meinem Fall sind Elemente (eine Elementklasse) einer solchen beobachtbaren Liste komplex und ich möchte keine Eigenschaft für jede Elementvariable implementieren. Aus diesem Grund fügte ich in die Element-Klasse eine BooleanProperty, die Änderung der Klasse angibt.


Element Klasse

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

beobachtbare Liste

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

Meine Frage dazu ist, Ansatz. Legen Sie wiederholt changeIndicatorProperty auf True fest, um das Änderungsereignis nicht auszulösen. Also, ich muss umkehren changeIndicatorProperty WertchangeIndicatorWrapper.set(!changeIndicatorWrapper.get()) jedes Mal. Es ist seltsam, oder?

Kann ich das Update-Ereignis programmatisch erzwingen?

Antwort

3

Es ist seltsam, nicht wahr?

Nein, das ist nicht überraschend. Damit eine Veränderung ausgelöst wird, muss eine Veränderung stattfinden. Wenn die BooleanProperty feststellt, dass keine Änderung stattfindet und daher die Listener nicht benachrichtigt werden, erfüllt dies immer noch den Vertrag von Property.

Eigentlich wird ein Property sowieso nicht benötigt. Was benötigt wird, ist ein Observable, der seine Beobachter benachrichtigt. Sie können dies tun, indem Sie die folgende Klasse mit und ruft 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) { 
      } 
     } 
    } 

} 

Beispiel:

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

} 
Verwandte Themen