Java 8:Observable List - 在属性更改时调用Invalidation Listener或Change Listener [英] Java 8: Observable List - Invalidation Listener nor Change Listener is called in case of property change
问题描述
我构建了一个自定义属性并将其添加到可观察列表中。但是如果属性内容发生更改,则不会调用侦听器。以下代码片段显示了构建:
I build a custom property and add it to a observable list. But no listener is called if property content is changed. The following code snippets shows you the 'building':
public static final class TestObject {
private final ReadOnlyStringWrapper title = new ReadOnlyStringWrapper();
private final BooleanProperty selected = new SimpleBooleanProperty(false);
public TestObject(String title) {
this.title.set(title);
}
public String getTitle() {
return title.get();
}
public ReadOnlyStringProperty titleProperty() {
return title.getReadOnlyProperty();
}
public boolean getSelected() {
return selected.get();
}
public BooleanProperty selectedProperty() {
return selected;
}
public void setSelected(boolean selected) {
this.selected.set(selected);
}
@Override
public int hashCode() {
return Objects.hash(title.get());
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
final TestObject other = (TestObject) obj;
return Objects.equals(this.title.get(), other.title.get());
}
@Override
public String toString() {
return "TestObject{" +
"title=" + title.get() +
", selected=" + selected.get() +
'}';
}
}
这是我的POJO类,内部属性值如name和selected。
This is my POJO class with my internal property values like name and selected.
public static final class TestProperty extends SimpleObjectProperty<TestObject> {
public TestProperty(String name) {
super(new TestObject(name));
init();
}
public TestProperty(TestObject testObject) {
super(testObject);
init();
}
public String getTitle() {
return getValue().getTitle();
}
public void setSelected(boolean selected) {
getValue().setSelected(selected);
}
public boolean getSelected() {
return getValue().getSelected();
}
public BooleanProperty selectedProperty() {
return getValue().selectedProperty();
}
public ReadOnlyStringProperty titleProperty() {
return getValue().titleProperty();
}
@Override
public void set(TestObject testObject) {
super.set(testObject);
init();
}
@Override
public void setValue(TestObject testObject) {
super.setValue(testObject);
init();
}
private void init() {
if (get() == null)
return;
get().titleProperty().addListener((v, o, n) -> fireValueChangedEvent());
get().selectedProperty().addListener((v, o, n) -> {
fireValueChangedEvent();
});
}
}
这是我基于POJO的自定义属性。所有属性更改都将触发我的自定义属性的更改事件。
This is my custom property based on the POJO. All property changes will fire a change event for my custom property.
@Test
public void testSimple() {
final AtomicInteger counter = new AtomicInteger(0);
final TestProperty testProperty = new TestProperty("Test");
testProperty.addListener(observable -> {
System.out.println("New state: " + testProperty.get().toString());
counter.incrementAndGet();
});
testProperty.setSelected(true);
testProperty.setSelected(false);
Assert.assertEquals(2, counter.intValue());
}
在此测试中,您可以看到属性更改事件正常。
In this test you can see that the property change event works fine.
@Test
public void testList() {
final AtomicInteger counter = new AtomicInteger(0);
final ObservableList<TestProperty> observableList = new ObservableListWrapper<>(new ArrayList<>());
observableList.add(new TestProperty("Test 1"));
observableList.add(new TestProperty("Test 2"));
observableList.add(new TestProperty("Test 3"));
observableList.addListener(new ListChangeListener<TestProperty>() {
@Override
public void onChanged(Change<? extends TestProperty> change) {
System.out.println("**************");
}
});
observableList.addListener((Observable observable) -> {
System.out.println("New state: " + ((TestProperty) observable).get().toString());
counter.incrementAndGet();
});
observableList.get(1).setSelected(true);
observableList.get(2).setSelected(true);
observableList.get(1).setSelected(false);
observableList.get(2).setSelected(false);
Assert.assertEquals(4, counter.intValue());
}
但在此代码中,您会看到可观察列表未被称为失效监听器,也未如果列表中的属性值已更改,则更改侦听器。
But in this code you see that the observable list not called the invalidation listener nor the change listener if a property value has changed in list.
有什么问题?
谢谢。
推荐答案
要创建一个可观察列表,如果列表元素的属性发生变化,将发送列表更新通知,您需要创建列表中包含提取。 提取器
是 Callback
,它将列表的每个元素映射到 Observable <的数组/ code>秒。如果任何
Observable
更改, InvalidationListener
s和 ListChangeListener
将被通知。
To create an observable list that will send "list updated" notifications if properties of elements of the list change, you need to create the list with an extractor. The extractor
is a Callback
that maps each element of the list to an array of Observable
s. If any of the Observable
s changes, InvalidationListener
s and ListChangeListener
s registered with the list will be notified.
所以在你的 testList()
方法中,你可以做到
So in your testList()
method, you can do
final ObservableList<TestProperty> observableList = FXCollections.observableList(
new ArrayList<>(),
(TestProperty tp) -> new Observable[]{tp.selectedProperty()});
如果标题能够更改,并且您还希望列表在发生时收到通知,你也可以这样做:
If the title were able to change, and you also wanted the list to receive notifications when that happened, you could do that too:
final ObservableList<TestProperty> observableList = FXCollections.observableList(
new ArrayList<>(),
(TestProperty tp) -> new Observable[]{tp.selectedProperty(), tp.titleProperty()});
请注意,因为提取器是回调
(本质上是一个函数),实现可以是任意复杂的(根据另一个属性的条件有条件地观察一个属性等)。
Note that because the extractor is a Callback
(essentially a function), the implementation can be arbitrarily complex (observe one property conditionally based on the value of another, etc).
这篇关于Java 8:Observable List - 在属性更改时调用Invalidation Listener或Change Listener的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!