Java 8:可观察列表 - 在属性更改的情况下调用无效侦听器或更改侦听器 [英] Java 8: Observable List - Invalidation Listener nor Change Listener is called in case of property change

查看:19
本文介绍了Java 8:可观察列表 - 在属性更改的情况下调用无效侦听器或更改侦听器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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 中的任何一个发生变化,InvalidationListeners 和 ListChangeListeners 将被通知到列表中.

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 Observables. If any of the Observables changes, InvalidationListeners and ListChangeListeners 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆