这是代码:
package sample;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.beans.property.ListProperty;
import javafx.beans.property.SimpleListProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
/**
* Created by IDEA on 29/07/15.
*/
public class ListPropertyTest {
public static void main(String[] args) {
ListProperty<String> lp =
new SimpleListProperty<>(FXCollections.observableArrayList());
lp.addListener(new ListChangeListener<String>() {
@Override
public void onChanged(Change<? extends String> c) {
while(c.next()) {
String action = c.wasPermutated() ? "perm"
: c.wasUpdated() ? "upd"
: c.wasRemoved() ? "rem"
: c.wasAdded() ? "add" : "";
System.out.println("Action: " + action);
System.out.println("Removed: " + c.getRemoved());
System.out.println("Added: " + c.getAddedSubList());
}
}
});
lp.addListener(new ChangeListener<ObservableList<String>>() {
@Override
public void changed(ObservableValue<? extends ObservableList<String>> observable, ObservableList<String> oldValue, ObservableList<String> newValue) {
System.out.println("List changed.");
System.out.println("Old: " + oldValue);
System.out.println("New: " + newValue);
}
});
lp.addListener(new InvalidationListener() {
@Override
public void invalidated(Observable observable) {
System.out.println("List invalid");
}
});
System.out.println("Add =========");
lp.addAll("one", "two");
System.out.println("Set =========");
lp.set(FXCollections.observableArrayList("two", "three"));
System.out.println("Remove ============");
lp.remove("two");
}
}
结果:
Add =========
List invalid
List changed.
Old: [one, two]
New: [one, two]
Action: add
Removed: []
Added: [one, two]
Set =========
List invalid
List changed.
Old: [one, two]
New: [two, three]
Action: rem
Removed: [one, two]
Added: [two, three]
Remove ============
List invalid
List changed.
Old: [three]
New: [three]
Action: rem
Removed: [two]
Added: []
如您所见,更改监听器仅在“Set”部分中行为正确。
最佳答案
这大部分是有意的行为。
一个ListProperty
既是 ObjectProperty<ObservableList>
和一个ObservableList
。
成为ObjectProperty<ObservableList>
意味着它包裹(包含对ObservableList
的引用)并且有setValue(ObservableList)
(或 set(...)
)和 getValue()
方法。作为ObjectProperty<ObservableList>
,您可以注册一个ChangeListener<ObservableList>
用它。如果对包装列表的引用发生变化,由某人调用 setValue(ObservableList)
,ChangeListener<ObservableList>.changed(...)
方法在任何已注册的 ChangeListener
上被调用,传入对 ListProperty
的引用本身,旧的ObservableList
引用,和新的ObservableList
引用。当您调用 set
时,您会看到此行为在您的代码中。
但是,当您只是更改列表的内容时,包装的列表仍然是相同的物理对象。所以“旧名单”和“新名单”是一回事。这是一个bug在这种情况下,更改监听器会触发通知;向@kleopatra 指出这一点致敬。
一个ListProperty
还实现 ObservableList
,通过委托(delegate) ObservableList
对包装列表实例的方法调用。这意味着如果列表的内容发生变化,任何ListChangeListener
已注册 ListProperty
得到通知。再次注意,在本例中只有一个列表对象;只是内容被修改了。
您可以获得有关 ObservableList
发生的更改的详细信息通过Change
对象传递给onChanged(...)
方法,正如您在 onChanged
的输出中观察到的那样方法。请注意c.getFrom()
和c.getTo()
还会为您提供已更改项目的索引。
我几乎从来不需要 ListProperty
:在绝大多数用例中,我只需使用简单的 ObservableList
就足够了执行。基于对象列表的控件(例如 ListView
和 TableView
)使用它们,因此您可以调用 setItems(...)
传递现有的ObservableList
如果您需要,或者(可能更常见)您可以调用 getItems()
检索当前列表并修改它。从上面的解释可以看出,ListProperty
允许这些控件观察任一类型的变化。但很可能在您自己的代码中,您将使用 ObservableList
直接直接使用比使用 ListProperty
更频繁.
关于java - ChangeListener 没有给出正确的旧值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31688493/