ObservableList/ObservableSet/ObservableMap是JavaFX库的观察者集合类,它们继承java.util包的List、Set、Map接口,同时还继承JavaFX的集合接口和Observable接口。
ObservableList/ObservableSet/ObservableMap这些观察者集合有2个新特性:
- 注册InvalidationListener接口,当集合数据失效时,触发invalidated事件通知,该事件继承自Observable接口。
- 注册ListChangeListener<E>接口,当几何数据修改时(增、删、改、重列)时,触发onChanged事件通知,该事件是JavaFX集合自定义的。
注意,这两个事件都能监听集合中元素的状态,根据条件触发。集合注册的监听事件同时可以监听集合的状态,也可以监听元素的状态,元素注册的事件只能监听元素的状态。
操作类:
package javafx8.ch03;
import javafx.beans.property.IntegerProperty;
import javafx.beans.Observable;
import javafx.util.Callback;
/**
* @copyright 2023-2022
* @package javafx8.ch03
* @file CallbackForListUpdateTest01.java
* @date 2023-08-19 19:06
* @author qiao wei
* @version 1.0
* @brief 继承Callback接口。
* @history
*/
public class CallbackForListUpdateTest01 implements Callback<IntegerProperty, Observable[]> {
public CallbackForListUpdateTest01() {}
@Override
public Observable[] call(IntegerProperty property) {
// 给属性注册invalidated,changed事件监听器
// property.addListener(ListUpdateTest01::invalidatedForIntegerProperty);
// property.addListener(ListUpdateTest01::changedForIntegerProperty);
System.out.println(property);
return new Observable[] {property};
}
}
操作类:
package javafx8.ch03;
import javafx.beans.Observable;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
/**
* @copyright 2023-2022
* @package learnjavafx8.javafx8.ch03
* @file ListUpdateTest01.java
* @date 2023-06-17 10:17
* @author qiao wei
* @version 1.0
* @brief 测试ObservableList及元素的invalidated事件,changed事件注册处理。通过FXCollections静态方法测试
* Callback接口的使用场景。
* @history
*/
public class ListUpdateTest01 {
public static void main(String[] args) {
CallbackForListUpdateTest01 callback = new CallbackForListUpdateTest01();
ObservableList<IntegerProperty> list = FXCollections.observableArrayList(callback);
list.addListener(ListUpdateTest01::invalidated);
list.addListener(ListUpdateTest01::onChanged);
// Create two elements instance
IntegerProperty p1 = new SimpleIntegerProperty(10);
IntegerProperty p2 = new SimpleIntegerProperty(20);
p1.addListener(ListUpdateTest01::invalidatedForIntegerProperty);
p1.addListener(ListUpdateTest01::changedForIntegerProperty);
/**
* 列表添加元素项。依次触发列表注册的invalidated事件,changed事件。
*/
System.out.println("向List中添加属性元素:添加元素p1。列表添加元素项。依次触发列表注册的invalidated事件," +
"changed事件。因为元素项本身没有被修改或失效,所以未触发元素项注册的invalidated事件和changed事件。");
list.add(p1);
System.out.println("向List中添加属性元素:" + "添加元素p2。列表添加元素项。依次触发列表注册的invalidated事件," +
"changed事件。因为元素项本身没有被修改或失效,所以未触发元素项注册的invalidated事件和changed事件。");
list.add(p2);
/**
* 修改集合中元素项内容。依次触发元素项注册的invalidated事件,列表注册的invalidated事件,列表注册的changed事件,
* 触发元素项注册的changed事件。
*/
System.out.println("修改属性的值" + "元素0的值修改为33。依次触发元素项注册的invalidated事件,列表注册的" +
"invalidated事件,列表注册的changed事件,触发元素项注册的changed事件。");
list.get(0).set(33);
/**
* 移除集合中元素项。因为元素项被删除,不会触发元素项的注册事件。操作依次触发列表注册的invalidated事件,
* changed事件。
*/
System.out.println("移除集合中元素项。因为元素项被删除,不会触发元素项的注册事件。操作依次触发列表注册的" +
"invalidated事件,changed事件。");
list.remove(1);
}
public static void invalidatedForIntegerProperty(Observable observable) {
System.out.println(observable);
System.out.println("invalidatedForIntegerProperty--------------------------\n");
}
public static void changedForIntegerProperty(ObservableValue<? extends Number> observable,
Number oldValue,
Number newValue) {
System.out.println(observable);
System.out.println("--------------------------changedForIntegerProperty\n");
}
/**
* @class ListUpdateTest01
* @date 2023-09-22 22:30
* @author qiao wei
* @version 1.0
* @brief Invalidated事件。
* @param
* @return
* @throws
*/
public static void invalidated(Observable observable) {
System.out.println(observable);
System.out.println("invalidatedForObservableList##########################");
}
/**
* @class ListUpdateTest01
* @date 2023-09-22 22:30
* @author qiao wei
* @version 1.0
* @brief Changed事件。
* @param
* @return
* @throws
*/
public static void onChanged(ListChangeListener.Change<? extends IntegerProperty> change) {
System.out.println(change);
System.out.println("#############################changedForObservableList\n");
}
}
运行结果:
向List中添加属性元素:添加元素p1。列表添加元素项。依次触发列表注册的invalidated事件,changed事件。因为元素项本身没有被修改或失效,所以未触发元素项注册的invalidated事件和changed事件。
IntegerProperty [value: 10]
[IntegerProperty [value: 10]]
invalidatedForObservableList##########################
{ [IntegerProperty [value: 10]] added at 0 }
#############################changedForObservableList
向List中添加属性元素:添加元素p2。列表添加元素项。依次触发列表注册的invalidated事件,changed事件。因为元素项本身没有被修改或失效,所以未触发元素项注册的invalidated事件和changed事件。
IntegerProperty [value: 20]
[IntegerProperty [value: 10], IntegerProperty [value: 20]]
invalidatedForObservableList##########################
{ [IntegerProperty [value: 20]] added at 1 }
#############################changedForObservableList
修改属性的值元素0的值修改为33。依次触发元素项注册的invalidated事件,列表注册的invalidated事件,列表注册的changed事件,触发元素项注册的changed事件。
IntegerProperty [value: 33]
invalidatedForIntegerProperty--------------------------
[IntegerProperty [value: 33], IntegerProperty [value: 20]]
invalidatedForObservableList##########################
{ updated at range [0, 1) }
#############################changedForObservableList
IntegerProperty [value: 33]
--------------------------changedForIntegerProperty
移除集合中元素项。因为元素项被删除,不会触发元素项的注册事件。操作依次触发列表注册的invalidated事件,changed事件。
IntegerProperty [value: 20]
[IntegerProperty [value: 33]]
invalidatedForObservableList##########################
{ [IntegerProperty [value: 20]] removed at 1 }
#############################changedForObservableList
可以看到注册事件的执行情况。先执行invalidated事件,后执行changed事件,对象本身注册的事件执行优先级最高。
触发事件的完整顺序:
观察者列表总共可以注册4类事件。列表invalidated、changed事件。元素项invalidated、changed事件。
只是列表增删元素项,只会依次触发列表invalidated、changed事件。
如果元素项修改,依次触发元素invalidated事件,列表invalidated事件,列表changed事件,元素changed事件。