【问题标题】:How to retrieve the changed item in an ObservableList via ListChangeListener如何通过 ListChangeListener 检索 ObservableList 中的更改项
【发布时间】:2018-04-28 07:09:10
【问题描述】:

ListChangeListener.Change.wasUpdated() 用于检测通过ObservableList.observableArrayList(Callback<E,Observable[]> extractor) 创建的ObservableLists 元素内的变化。

如何检索导致更改被触发的确切项目?

编辑

可能问题不够清楚,我举个例子吧。

class Foo {
    private StringProperty name = new SimpleStringProperty();
    public final StringProperty nameProperty() { return name; }
    public final String getName() { return name.get(); }
    public final void setName(String n) { name.set(n); }
    public Foo(String fooName) { setName(fooName); }
}

// Creates an ObservableList with an extractor
ObservableList<Foo> fooList = FXCollections.observableArrayList(foo -> new Observable[] { foo.nameProperty() });
Foo fooA = new Foo("Hello");
Foo fooB = new Foo("Kitty");
fooList.add(fooA);
fooList.add(fooB);

fooList.addListener(new ListChangeListener<Foo>() {
     public void onChanged(Change<Foo> c) {
         while (c.next()) {
            if (c.wasUpdated()) {
                // One or more of the elements in list has/have an internal change, but I have no idea which element(s)!
            }
        }
    }
});

fooB.setName("Mickey");

fooB.setName() 将触发 ListChangeListener 的更改,wasUpdated() 条件将返回 true。但是,我无法知道是 fooB 在侦听器中发生了变化。

这可能看起来微不足道,但我有一个地图应用程序,其中列表存储地图必须呈现的内容。当其中一项更改其位置(即纬度/经度)时,我需要在地图上重新绘制。如果我不知道哪个项目改变了位置,我将不得不重新绘制我已经拥有的所有内容。

【问题讨论】:

  • 嗯 ...change.getList().get(change.getFrom()) 不工作?

标签: java javafx observablelist


【解决方案1】:

您可以获得已更改项目的索引,这为您提供了一些有用的信息:

import javafx.beans.Observable;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener.Change;
import javafx.collections.ObservableList;

public class ListUpdateTest {

    public static void main(String[] args) {

        ObservableList<Foo> fooList = FXCollections.observableArrayList(foo -> new Observable[] { foo.nameProperty() });
        Foo fooA = new Foo("Hello");
        Foo fooB = new Foo("Kitty");
        fooList.add(fooA);
        fooList.add(fooB);

        fooList.addListener((Change<? extends Foo> c) -> {
             while (c.next()) {
                if (c.wasUpdated()) {
                    int start = c.getFrom() ;
                    int end = c.getTo() ;
                    for (int i = start ; i < end ; i++) {
                        System.out.println("Element at position "+i+" was updated to: " +c.getList().get(i).getName() );
                    }
                }
            }
        });

        fooB.setName("Mickey");
    }

    public static class Foo {
        private StringProperty name = new SimpleStringProperty();
        public final StringProperty nameProperty() { return name; }
        public final String getName() { return name.get(); }
        public final void setName(String n) { name.set(n); }
        public Foo(String fooName) { setName(fooName); }
    }
}

请注意,您无法从列表更改事件中确定这些列表元素中发生更改的实际属性(因此,如果您的提取器指向两个或更多属性,则无法找到其中哪些属性发生了更改),并且没有办法得到以前的值。不过,这对于您的用例可能已经足够了。

【讨论】:

  • 挑剔:无需访问“外部”字段,更改包含列表(如您所知,但新手可能不会:)
  • 非常感谢,我完全忽略了使用索引。
【解决方案2】:

直接来自docs

典型的用法是观察 ObservableList 上的变化,以便挂钩或取消挂钩(或添加或删除侦听器),或者为了保持该 ObservableList 中每个元素的某些不变性。执行此操作的常见代码模式如下所示:

 ObservableList theList = ...;

 theList.addListener(new ListChangeListener<Item>() {
     public void onChanged(Change<tem> c) {
         while (c.next()) {
             if (c.wasPermutated()) {
                     for (int i = c.getFrom(); i < c.getTo(); ++i) {
                          //permutate
                     }
                 } else if (c.wasUpdated()) {
                          //update item
                 } else {
                     for (Item remitem : c.getRemoved()) {
                         remitem.remove(Outer.this);
                     }
                     for (Item additem : c.getAddedSubList()) {
                         additem.add(Outer.this);
                     }
                 }
             }
         }
     });

 }

【讨论】:

  • 说句公道话,看到这个答案后,我让我的同事看看我的问题,他并没有完全明白我想问的问题。当我最初发布这个问题时,我以为它简短、简单、直接,但事实并非如此。
猜你喜欢
  • 1970-01-01
  • 2020-07-14
  • 2019-05-31
  • 2013-06-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-02
相关资源
最近更新 更多