如何通过 ListChangeListener 检索 ObservableList 中的更改项
How to retrieve the changed item in an ObservableList via ListChangeListener
有ListChangeListener.Change.wasUpdated()
which is used to detect changes within elements for ObservableList
s created via ObservableList.observableArrayList(Callback<E,Observable[]> extractor)
.
如何检索导致触发更改的确切项目?
编辑
可能问题不够清楚,我举个例子吧
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()
条件会 return true
。但是,我无法知道它是 fooB
在监听器中发生了变化。
这可能看起来微不足道,但我有一个地图应用程序,其中的列表存储了地图必须呈现的内容。当其中一项改变其位置时(即 lat/long),我需要在地图上重新绘制。如果我不知道哪个项目改变了位置,我将不得不重新绘制我已有的所有内容。
直接来自 docs。
Typical usage is to observe changes on an ObservableList in order to hook or unhook (or add or remove a listener) or in order to maintain some invariant on every element in that ObservableList. A common code pattern for doing this looks something like the following:
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);
}
}
}
}
});
}
您可以获得已更改项目的索引,这会为您提供一些有用的信息:
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); }
}
}
请注意,您无法从列表更改事件中确定那些列表元素中发生更改的实际属性(因此,如果您的提取器指向两个或更多属性,则无法找到哪些属性发生了更改) ,并且没有办法得到以前的值。不过,这对于您的用例来说可能已经足够了。
有ListChangeListener.Change.wasUpdated()
which is used to detect changes within elements for ObservableList
s created via ObservableList.observableArrayList(Callback<E,Observable[]> extractor)
.
如何检索导致触发更改的确切项目?
编辑
可能问题不够清楚,我举个例子吧
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()
条件会 return true
。但是,我无法知道它是 fooB
在监听器中发生了变化。
这可能看起来微不足道,但我有一个地图应用程序,其中的列表存储了地图必须呈现的内容。当其中一项改变其位置时(即 lat/long),我需要在地图上重新绘制。如果我不知道哪个项目改变了位置,我将不得不重新绘制我已有的所有内容。
直接来自 docs。
Typical usage is to observe changes on an ObservableList in order to hook or unhook (or add or remove a listener) or in order to maintain some invariant on every element in that ObservableList. A common code pattern for doing this looks something like the following:
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);
}
}
}
}
});
}
您可以获得已更改项目的索引,这会为您提供一些有用的信息:
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); }
}
}
请注意,您无法从列表更改事件中确定那些列表元素中发生更改的实际属性(因此,如果您的提取器指向两个或更多属性,则无法找到哪些属性发生了更改) ,并且没有办法得到以前的值。不过,这对于您的用例来说可能已经足够了。