Java8:可观察列表-在属性更改的情况下调用无效侦听器或更改侦听器
我构建了一个自定义属性并将其添加到可观察列表中。但如果属性内容发生更改,则不会调用侦听器。以下代码片段向您展示了“建筑”:Java8:可观察列表-在属性更改的情况下调用无效侦听器或更改侦听器,java,properties,javafx,observable,changelistener,Java,Properties,Javafx,Observable,Changelistener,我构建了一个自定义属性并将其添加到可观察列表中。但如果属性内容发生更改,则不会调用侦听器。以下代码片段向您展示了“建筑”: public static final class TestObject { private final ReadOnlyStringWrapper title = new ReadOnlyStringWrapper(); private final BooleanProperty selected = new SimpleBooleanProperty(f
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
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();
});
}
}
在这个测试中,您可以看到属性更改事件工作正常
@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());
}
@测试
公共void测试列表(){
最终AtomicInteger计数器=新的AtomicInteger(0);
最终ObservableList ObservableList=新ObservableList包装器(新ArrayList());
添加(新的TestProperty(“测试1”));
添加(新测试属性(“测试2”));
添加(新测试属性(“测试3”));
observableList.addListener(新的ListChangeListener(){
@凌驾
public void onChanged(Change每当修改列表中包含的属性时,ObservableList不会通知侦听器,而是在通知列表时通知侦听器
修改测试时可以看到这一点:
@Test
public void testList() {
final AtomicInteger counter = new AtomicInteger(0);
final ObservableList<TestProperty> observableList = new ObservableListWrapper<>(new ArrayList<>());
observableList.addListener(new ListChangeListener<TestProperty>() {
@Override
public void onChanged(Change<? extends TestProperty> change) {
System.out.println("**************");
counter.incrementAndGet();
}
});
observableList.add(new TestProperty("Test 1"));
observableList.add(new TestProperty("Test 2"));
observableList.add(new TestProperty("Test 3"));
observableList.get(1).setSelected(true);
observableList.get(2).setSelected(true);
observableList.get(1).setSelected(false);
observableList.get(2).setSelected(false);
Assert.assertEquals(3, counter.intValue());
}
@测试
公共void测试列表(){
最终AtomicInteger计数器=新的AtomicInteger(0);
最终ObservableList ObservableList=新ObservableList包装器(新ArrayList());
observableList.addListener(新的ListChangeListener(){
@凌驾
public void onChanged(Change以下代码显示了可观察列表的一个简单实现,其中包含可观察值:
public class ObservableValueListWrapper<E extends ObservableValue<E>> extends ObservableListWrapper<E> {
public ObservableValueListWrapper(List<E> list) {
super(list, o -> new Observable[] {o});}}
public类observeValueListWrapper扩展了observeListWrapper{
公共ObservaleValueListWrapper(列表){
super(list,o->newobservable[]{o});}
或者,您必须使用POJO创建列表:
final ObservableList<MyPOJO> list = new ObservableListWrapper<>(new ArrayList(), o -> new Observable[] { new MyPOJOProperty(o) });
final observeList list=new observeListWrapper(new ArrayList(),o->new observeable[]{new MyPOJOProperty(o)});
或者你这样使用它:
final ObservableList<MyPOJO> list = new ObservableListWrapper<>(new ArrayList(), o -> { return new Observable[] {
o.value1Property(),
o.value2Property(),
...};});
final observeList list=new observeListWrapper(new ArrayList(),o->{return new observeable[]{
o、 value1Property(),
o、 value2Property(),
...};});
就是这样!谢谢。创建一个可观察列表,该列表将发送“列表更新”通知如果列表元素的属性更改,则需要使用创建列表。提取器
是一个回调
,它将列表中的每个元素映射到一个可观察
s数组。如果任何可观察
s更改,无效侦听器
s和列表更改侦听器
s在名单上登记的人将收到通知
因此,在您的testList()
方法中,您可以
final ObservableList<TestProperty> observableList = FXCollections.observableList(
new ArrayList<>(),
(TestProperty tp) -> new Observable[]{tp.selectedProperty()});
final ObservableList ObservableList=FXCollections.ObservableList(
新建ArrayList(),
(TestProperty tp)->新的可观察[]{tp.selectedProperty()});
如果标题可以更改,并且您还希望列表在更改时接收通知,您也可以这样做:
final ObservableList<TestProperty> observableList = FXCollections.observableList(
new ArrayList<>(),
(TestProperty tp) -> new Observable[]{tp.selectedProperty(), tp.titleProperty()});
final ObservableList ObservableList=FXCollections.ObservableList(
新建ArrayList(),
(TestProperty tp)->新的可观察[]{tp.selectedProperty(),tp.titleProperty()});
请注意,由于提取器是一个回调函数(本质上是一个函数),因此实现可以任意复杂(根据另一个属性的值有条件地观察一个属性,等等).但侦听器方法参数类中的“change.wasdupdated”是什么意思?是的,这里的javadoc有点混乱!这表示observablelist中链接到的项(即索引值为0、1、2等)是否已更新(即在该索引处放置了新对象),而不是对象本身已更改。这样做的目的是允许您在ListChangeListener中决定是否要在上注册ChangeListener(可能)列表中的ObservableProperty。应该注意的是,ObservableList不需要ObservableProperty作为成员,它可以保存对象类型。但有一些实现可以做到这一点,我想做的是:如果列表中的属性值发生了更改,则获取回调?嗯……我应该预料到questions=)我会说不。我没有遇到过它,我只是浏览了一下javadoc-那里没有什么值得注意的。但是,我认为装饰一个ObservableList来提供该功能是相当简单的。我将在上面添加一个快速示例。这太疯狂了:)列表有一个无效监听器,类似于可观察值的无效监听器。如果您有一个属性,则在该属性更改其值之一时调用无效监听器。我认为可观察列表必须具有与属性相同的行为:如果列表中的属性已更改,则必须调用无效监听器。Th我认为,必须检查添加的对象是否是一个可观察的值。不过,您正在复制API中的现有功能,还使用了不属于公共API的类。顺便说一句(尽管这与您的问题密切相关),observeListWrapper
不是公共API的一部分,不应该真正使用。不保证它会出现在JavaFX的未来版本中。要创建observeList
s(和其他可观察的集合),使用中的工厂方法。您可以举一个示例,其中您可以侦听类Person的ObservableList中的更改(侦听名称、姓氏等)。此示例没有为90%的情况提供简单示例:)看起来很有希望。如果可以的话,请提供一些澄清:有什么原因不能使用链表而不是数组列表吗?@Ruben9922使用链表进行了尝试,效果很好。@James_D实际上问题似乎出在我使用的ChoiceBox
上,而不是ObservableList
本身;列表本身可以很好地更新。
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()});