gpt4 book ai didi

Java 8 : Observable List - Invalidation Listener nor Change Listener is called in case of property change

转载 作者:搜寻专家 更新时间:2023-10-31 08:08:58 27 4
gpt4 key购买 nike

我构建了一个自定义属性并将其添加到可观察列表中。但是,如果属性内容发生更改,则不会调用任何监听器。以下代码片段向您展示了“建筑”:

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 类,具有我的内部属性值,如名称和选定。

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 的自定义属性。所有属性更改都会为我的自定义属性触发更改事件。

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

在此测试中,您可以看到属性更改事件工作正常。

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

但在这段代码中,如果列表中的属性值发生变化,可观察列表不会调用失效监听器或更改监听器。

怎么了?

谢谢。

最佳答案

要创建一个可观察列表,如果列表元素的属性发生变化,将发送“列表更新”通知,您需要使用 extractor 创建列表. extractor 是一个 Callback,它将列表的每个元素映射到一个 Observable 数组。如果任何 Observable 发生变化,将通知在列表中注册的 InvalidationListenerListChangeListener

所以在你的testList()方法中,你可以做

final ObservableList<TestProperty> observableList = FXCollections.observableList(
new ArrayList<>(),
(TestProperty tp) -> new Observable[]{tp.selectedProperty()});

如果标题能够更改,并且您还希望列表在发生更改时收到通知,您也可以这样做:

final ObservableList<TestProperty> observableList = FXCollections.observableList(
new ArrayList<>(),
(TestProperty tp) -> new Observable[]{tp.selectedProperty(), tp.titleProperty()});

请注意,因为提取器是一个Callback(本质上是一个函数),实现可以是任意复杂的(根据另一个属性的值有条件地观察一个属性,等等)。

关于Java 8 : Observable List - Invalidation Listener nor Change Listener is called in case of property change,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26730034/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com