Java 8:可观察列表 - 在属性更改的情况下调用无效侦听器或更改侦听器 [英] 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.
怎么了?
谢谢.
推荐答案
要创建一个可观察列表,如果列表元素的属性发生变化,它将发送列表更新"通知,您需要创建带有 提取器.extractor
是一个 Callback
,它将列表的每个元素映射到一个 Observable
数组.如果 Observable
中的任何一个发生变化,InvalidationListener
s 和 ListChangeListener
s 将被通知到列表中.
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()});
请注意,因为提取器是一个 Callback
(本质上是一个函数),所以实现可以是任意复杂的(根据另一个属性的值有条件地观察一个属性,等等).
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:可观察列表 - 在属性更改的情况下调用无效侦听器或更改侦听器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!