JavaFX中的观察集合(Observable Collections)继承自Java的集合(Collections)。Java集合提供了List、Map、Set三种集合接口。JavaFX在Java集合基础上派生出可以监听集合内容变化的三种集合接口。接口如下:
ObservableList
ObservableSet
ObservableMap
Java的 集合接口不仅继承Java的List、Map、Set接口,同时还继承JavaFX中的Observable接口。继承关系如下图所示:
相较于Java中的集合,JavaFX中继承Observable接口的集合有以下新功能:
- 支持监听失效事件。
- 支持监听改变事件。可以给继承Observable接口的类注册改变监听器,当集合内容发生变化是进行通知。
ObservableList接口的继承关系如下:
ObservableList接口的addListener()、removeListener()方法注册/注销ListChangeListener事件(ListChangeListener实例),当ObservableList发生改变事件时触发ListChangedListener事件。
void addListener(ListChangeListener<? super E> listener);
void removeListener(ListChangeListener<? super E> listener);
注意,ObservableList接口重写了(Override)Observable接口中的addListener()、removeListener()方法,在Observable接口中,addListener()、removeListener()方法注册/注销InvalidationListener接口。
void addListener(InvalidationListener listener);
void removeListener(InvalidationListener listener);
测试ObservableList注册InvalidationListener接口:
package learnjavafx8.ch03;
import javafx.beans.Observable;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
/**
* @copyright 2023-2022
* @package learnjavafx8.ch03
* @file ListInvalidationTest.java
* @date 2023-06-16 23:13
* @author qiao wei
* @version 1.0
* @brief Test invalidation event. Invalidation event includes add, remove, replace and sort.
* @history
*/
public class ListInvalidationTest {
public static void main(String[] args) {
String one = "one";
// Create a list with some elements without changelistener
ObservableList<String> list = FXCollections.observableArrayList(one, "two");
System.out.println(list);
// ObservableList implements Observable interface, Register an InvalidationListener to
// the list
list.addListener(ListInvalidationTest::invalidated);
System.out.println("Before adding element three.------------------------------------");
// Add element to list, list fire invalidation event
list.add("three");
// System.out.println(list);
System.out.println("After adding element three------------------------------------\n");
System.out.println("Before adding elements four and five.---------------------------");
list.addAll("four", "five");
// System.out.println(list);
System.out.println("Before adding elements four and five.-------------------------\n");
// Replace the element in 0 index
System.out.println("Before replacing one in index 0.--------------------------------");
list.set(3, one);
// System.out.println(list);
System.out.println("After replacing one in index 0.-------------------------------\n");
}
/**
* @class ListInvalidationTest
* @date 2023-06-16 23:14
* @author qiao wei
* @version 1.0
* @brief Invalidate event. This method is called if an Observable becomes invalid.
* @param list The Observable that became invalid.
* @return
* @throws
*/
public static void invalidated(Observable list) {
System.out.println("++++++Invalidation event is fired+++++++.");
System.out.println(list);
}
}
运行结果:
[one, two]
Before adding element three.------------------------------------
++++++Invalidation event is fired+++++++.
[one, two, three]
After adding element three------------------------------------
Before adding elements four and five.---------------------------
++++++Invalidation event is fired+++++++.
[one, two, three, four, five]
Before adding elements four and five.-------------------------
Before replacing one in index 0.--------------------------------
++++++Invalidation event is fired+++++++.
[one, two, three, one, five]
After replacing one in index 0.-------------------------------
Process finished with exit code 0
测试ObservableList接口注册InvalidationListener接口和ListChangeListener接口。
package learnjavafx8.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.ch03
* @file ListInvalidationTest01.java
* @date 2023-06-12 16:42
* @author qiao wei
* @version 1.0
* @brief ObservableList实例对invalidated和onChanged事件的处理。注意区别ObservableList中保存的属性的
* invalidated和changed事件处理,ObservableList增删Property触发ObservableList的invalidated
* 事件和changed事件,Property改变自己的值触发Property的invalidated事件和changed事件。
* @history
*/
public class ListInvalidationTest01 {
public static void main(String[] args) {
ObservableList<IntegerProperty> properties = FXCollections.observableArrayList();
// ObservableList添加invalidated事件和changed事件监听器
properties.addListener(ListInvalidationTest01::onChanged);
properties.addListener(ListInvalidationTest01::invalidated);
IntegerProperty property01 = new SimpleIntegerProperty(22);
// IntegerProperty property02 = new SimpleIntegerProperty(301);
// Property添加invalidated事件监听器,当Property“失效”时触发
property01.addListener(ListInvalidationTest01::invalidatedForProperty);
// property02.addListener(ListInvalidationTest01::invalidatedForProperty);
// Property添加changed事件监听器,当属性“改变”时触发
property01.addListener(ListInvalidationTest01::changedForProperty);
// property02.addListener(ListInvalidationTest01::changedForProperty);
// ObservableList添加元素。触发ObservableList的invalidated事件和changed事件。没有失效或改变
// property01和property02,不会触发Property的invalidated和changed事件
properties.add(property01);
// properties.add(property02);
// 修改Property数值,触发invalidated事件和changed事件。不会触发Property所在的ObservableList的
// invalidated事件和changed事件
System.out.println("----------------Property test------------------------");
properties.get(0).set(10);
System.out.println("----------------Property test------------------------\n");
// 删除ObservableList中元素,触发ObservableList的invali事件(如果注册changed事件,同时也会触发)
System.out.println("============ObservableList test======================");
properties.remove(0);
System.out.println("============ObservableList test==================\n");
}
/**
* @class ListInvalidationTest01
* @date 2023-06-12 19:00
* @author qiao wei
* @version 1.0
* @brief Property invalidated event.
* @param
* @return
* @throws
*/
public static void invalidatedForProperty(Observable observable) {
System.out.println("Property invalidated event &&&&&&&&&&&&&&&&&&&&&&");
System.out.println(observable.toString());
System.out.println("Property invalidated event &&&&&&&&&&&&&&&&&&&&&&\n");
}
/**********************************************************************************************
* @class ListInvalidationTest01
* @date 2023-02-01 14:49
* @author qiao wei
* @version 1.0
* @brief Property changed event
* @param
* @return
* @throws
*********************************************************************************************/
public static void changedForProperty(ObservableValue<? extends Number> observable,
Number oldValue,
Number newValue) {
System.out.println("&&&&&&&&&&&&&&&&&&&&&& Property changed event");
// Observable instance's value is the new value
System.out.println("Property's value : " + observable.getValue().intValue());
System.out.println("Number changed : ");
System.out.println("Old = " + oldValue.toString() + ", New = " + newValue.toString());
System.out.println("&&&&&&&&&&&&&&&&&&&&&& Property changed event\n");
}
/**********************************************************************************************
* @class ListInvalidationTest01
* @date 2023-01-31 18:11
* @author qiao wei
* @version 1.0
* @brief ObservableList invalidated event
* @param
* @return
* @throws
*********************************************************************************************/
public static void invalidated(Observable observable) {
System.out.println("ObservableList invalidated event ----------------------------");
System.out.println(observable.toString());
System.out.println("ObservableList invalidated event ----------------------------\n");
}
/**********************************************************************************************
* @class ListInvalidationTest01
* @date 2023-01-31 18:11
* @author qiao wei
* @version 1.0
* @brief ObservableList onChanged event
* @param
* @return
* @throws
*********************************************************************************************/
public static void onChanged(ListChangeListener.Change<? extends IntegerProperty> change) {
System.out.println("-------------------------------ObservableList onChanged event");
if (change.next()) {
System.out.println("&&&" + change.toString());
}
System.out.println("-------------------------------ObservableList onChanged event\n");
}
}
运行结果:
ObservableList invalidated event ----------------------------
[IntegerProperty [value: 22]]
ObservableList invalidated event ----------------------------
-------------------------------ObservableList onChanged event
&&&{ [IntegerProperty [value: 22]] added at 0 }
-------------------------------ObservableList onChanged event
----------------Property test------------------------
Property invalidated event &&&&&&&&&&&&&&&&&&&&&&
IntegerProperty [value: 10]
Property invalidated event &&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&& Property changed event
Property's value : 10
Number changed :
Old = 22, New = 10
&&&&&&&&&&&&&&&&&&&&&& Property changed event
----------------Property test------------------------
============ObservableList test======================
ObservableList invalidated event ----------------------------
[]
ObservableList invalidated event ----------------------------
-------------------------------ObservableList onChanged event
&&&{ [IntegerProperty [value: 10]] removed at 0 }
-------------------------------ObservableList onChanged event
============ObservableList test==================
Process finished with exit code 0