JavaFX - ObservableList和列表的项目更改

时间:2017-01-06 20:02:03

标签: javafx observable

This answer可观察列表提供解决方案,该列表将发送"列表更新" 通知列表元素的属性更改

在我的例子中,这种可观察列表的元素(元素类)很复杂,我不想为每个成员变量实现属性。因此,我在元素类中添加了一个 BooleanProperty ,表示类的更改。

元素类

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())。这很奇怪,不是吗?

我可以以编程方式强制更新事件吗?

1 个答案:

答案 0 :(得分: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();
    }

}