JavaFX - ObservableList和列表的项目更改 [英] JavaFX – ObservableList and list's item change
问题描述
This答案为可观察列表提供解决方案,如果列表元素的属性列表更新 通知 >改变。
This answer provides a solution for an observable list that will send "list updated" notifications if properties of elements of the list change.
在我的例子中,这种可观察列表的元素(元素类)很复杂,我不知道喜欢为每个成员变量实现属性。因此,我在元素类中添加了一个 BooleanProperty ,表示类的更改。
In my case, elements (a Element class) of such observable list are complex and I don't like to implement property for each member variable. Due to this, I added into the Element class a BooleanProperty that indicates change of the class.
元素类
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());
}
}
Observable List
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())
。这很奇怪,不是吗?
My question is about this approach. Repeatedly set the changeIndicatorProperty to true not fire the change event. So, I need to reverse changeIndicatorProperty value changeIndicatorWrapper.set(!changeIndicatorWrapper.get())
each time. It is strange, isn't it?
我可以以编程方式强制更新事件吗?
Can I force programatically the update event?
推荐答案
这很奇怪,不是吗?
It is strange, isn't it?
不,这不是'令人惊讶的。要触发更改,需要进行更改。如果 BooleanProperty
确定没有发生任何更改,因此听众没有收到任何通知,这仍然符合 Property
。
No this isn't surprising. For a change to be triggered a change needs to happen. If the BooleanProperty
determines no change does happen and therefore the listeners are not notified of anything, this still satisfies the contract of Property
.
实际上不需要 Property
。我们需要的是一个 Observable
,它会通知它的观察者。您可以通过使用以下类并调用使
无效来执行此操作:
Actually a Property
isn't needed anyways. What is needed is a Observable
that notifies it's observers. You could do this by using the following class and calling 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();
}
}
这篇关于JavaFX - ObservableList和列表的项目更改的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!