20231224更新:增加Observable***集合处理监听事件。
示例一:
自定义类继承InvalidationListener接口,当数据失效时,触发该接口的invalidated事件。
Book数据类,其中的变量分别是StringProperty类型和DoubleProperty类型。分别注册InvalidationListener接口的实现ObservableEvent类。
package javafx8.ch03.observablelist;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
/**
* @copyright 2003-2023
* @package javafx8.ch03.observablelist
* @file Book.java
* @date 2023-12-22 16:13
* @author qiao wei
* @version 1.0
* @brief
* @history
*/
public class Book {
public Book(String isbn, String bookTitle, double price) {
isbnProperty = new SimpleStringProperty(this, "ISBN", isbn);
bookTitleProperty = new SimpleStringProperty(this, "Book", bookTitle);
priceProperty = new SimpleDoubleProperty(this, "Price", price);
// 变量属性注册Invalidated事件和Changed事件。
invalidationEvent = new InvalidationEvent();
isbnProperty.addListener(invalidationEvent::invalidated);
bookTitleProperty.addListener(invalidationEvent::invalidated);
priceProperty.addListener(invalidationEvent::invalidated);
changeEvent = new ChangeEvent();
isbnProperty.addListener(changeEvent::changed);
bookTitleProperty.addListener(changeEvent::changed);
priceProperty.addListener(changeEvent::changed);
}
public String getIsbn() {
return isbnProperty.get();
}
public void setIsbn(String isbn) {
isbnProperty.set(isbn);
}
public String getBookTitle() {
return bookTitleProperty.get();
}
public void setBookTitle(String bookTitle) {
bookTitleProperty.set(bookTitle);
}
public double getPrice() {
return priceProperty.get();
}
public void setPrice(double price) {
priceProperty.set(price);
}
public static final String ISBN = "ISBN";
public static final String BOOK = "Book";
public static final String PRICE = "Price";
private StringProperty isbnProperty;
private StringProperty bookTitleProperty;
private DoubleProperty priceProperty;
private InvalidationEvent invalidationEvent;
private ChangeEvent changeEvent;
}
InvalidationEvent类,继承InvalidationListener接口:
package javafx8.ch03.observablelist;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.StringProperty;
/**
* @copyright 2003-2023
* @package javafx8.ch03.observablelist
* @file InvalidationEvent.java
* @date 2023-12-22 16:22
* @author qiao wei
* @version 1.0
* @brief
* @history
*/
public class InvalidationEvent implements InvalidationListener {
public InvalidationEvent() {}
@Override
public void invalidated(Observable observable) {
System.out.println("········································调用Invalidated方法");
String name = null;
StringProperty stringProperty = null;
DoubleProperty doubleProperty = null;
if (observable instanceof StringProperty) {
stringProperty = (StringProperty) observable;
name = stringProperty.getName();
} else if (observable instanceof DoubleProperty) {
doubleProperty = (DoubleProperty) observable;
name = doubleProperty.getName();
}
switch (name) {
case Book.ISBN:
System.out.println(name + ": " + stringProperty.get());
break;
case Book.BOOK:
System.out.println(name + ": " + stringProperty.get());
break;
case Book.PRICE:
System.out.println(name + ": " + doubleProperty.get());
break;
default:
break;
}
System.out.println("········································调用Invalidated方法");
System.out.println();
}
}
ChangeEvent类,继承ChangeListener
package javafx8.ch03.observablelist;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
/**
* @copyright 2003-2023
* @package javafx8.ch03.observablelist
* @file ChangeEvent.java
* @date 2023-12-23 17:23
* @author qiao wei
* @version 1.0
* @brief
* @history
*/
public class ChangeEvent implements ChangeListener {
public ChangeEvent() {}
@Override
public void changed(ObservableValue observableValue, Object oldValue, Object newValue) {
System.out.println("调用Changed方法+++++++++++++++++++++++++++++++++++");
String name = null;
StringProperty stringProperty = null;
DoubleProperty doubleProperty = null;
if (observableValue instanceof StringProperty) {
stringProperty = (StringProperty) observableValue;
name = stringProperty.getName();
} else if (observableValue instanceof DoubleProperty) {
doubleProperty = (DoubleProperty) observableValue;
name = doubleProperty.getName();
}
switch (name) {
case Book.ISBN:
System.out.println(name + ": " + stringProperty.get());
break;
case Book.BOOK:
System.out.println(name + ": " + stringProperty.get());
break;
case Book.PRICE:
System.out.println(name + ": " + doubleProperty.get());
break;
default:
break;
}
System.out.println("调用Changed方法+++++++++++++++++++++++++++++++++++");
System.out.println();
}
}
测试代码:
package javafx8.ch03.observablelist;
/**
* @copyright 2003-2023
* @package javafx8.ch03.observablelist
* @file BookTest.java
* @date 2023-12-22 16:35
* @author qiao wei
* @version 1.0
* @brief
* @history
*/
public class BookTest {
public static void main(String[] args) {
test01();
}
private static void test01() {
Book book01 = new Book("123", "Test01", 22.55D);
book01.setIsbn("222---");
book01.setPrice(22.3d);
}
}
运行结果:
········································调用Invalidated方法
ISBN: 222---
调用Changed方法+++++++++++++++++++++++++++++++++++
ISBN: 222---
········································调用Invalidated方法
Price: 22.3
调用Changed方法+++++++++++++++++++++++++++++++++++
Price: 22.3
程序更新String类型、double类型数据,也许是应为Observable接口是ObservableValue接口的父类,先后依次触发invalidated事件,changed事件。
集合的Invalidated事件是因为集合继承了Observable接口,但是没有继承ObservableValue接口,所以没有属性Property中定义的changed事件。但是集合自身定义了***ChangeListener.Change,类似changed事件。绑定集合的事件类如下:
ListInvalidatedEvent类:
package javafx8.ch03.observablelist;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.collections.ObservableList;
/**
* @copyright 2003-2023
* @package javafx8.ch03.observablelist
* @file ListInvalidatedEvent.java
* @date 2023-12-23 19:07
* @author qiao wei
* @version 1.0
* @brief
* @history
*/
public class ListInvalidatedEvent implements InvalidationListener {
/**
* @class ListInvalidatedEvent
* @date 2023-12-23 19:41
* @author qiao wei
* @version 1.0
* @brief
* @param
* @return
* @throws
*/
@Override
public void invalidated(Observable observable) {
System.out.println("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&调用集合Invalidated方法");
System.out.println("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&调用集合Invalidated方法");
if (observable instanceof ObservableList) {
ObservableList books = (ObservableList) observable;
System.out.println("打印集合中所有元素信息:");
for (Book book: books) {
System.out.println(book.getBookTitle() + ", " +
book.getIsbn() + ", " +
book.getPrice()
);
}
System.out.println("集合中元素个数:" + books.size());
}
System.out.println("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&调用集合Invalidated方法");
System.out.println("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&调用集合Invalidated方法");
System.out.println();
}
}
ListChangeEvent类:
package javafx8.ch03.observablelist;
import javafx.collections.ListChangeListener;
/**
* @copyright 2003-2023
* @package javafx8.ch03.observablelist
* @file ListChangeEvent.java
* @date 2023-12-24 11:18
* @author qiao wei
* @version 1.0
* @brief
* @history
*/
public class ListChangeEvent implements ListChangeListener {
public ListChangeEvent() {}
@Override
public void onChanged(Change change) {
System.out.println("】】】】】】】】】】】】】】】】】调用集合onChanged方法");
}
}
测试类BookTest代码,测试在test02函数中。
package javafx8.ch03.observablelist;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import javafx.beans.InvalidationListener;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
/**
* @copyright 2003-2023
* @package javafx8.ch03.observablelist
* @file BookTest.java
* @date 2023-12-22 16:35
* @author qiao wei
* @version 1.0
* @brief
* @history
*/
public class BookTest {
public static void main(String[] args) {
// test01();
test02();
}
private static void test01() {
Book book01 = new Book("123", "Test01", 22.55D);
book01.setIsbn("987654321");
book01.setPrice(22.3d);
}
/**
* @class BookTest
* @date 2023-12-24 10:24
* @author qiao wei
* @version 1.0
* @brief 将数据插入ObservableList实例books,给books注册Invalidated事件,并测试验证Invalidated事件。
* @param
* @return
* @throws
*/
private static void test02() {
Book book01 = new Book("123", "Test01", 22.55D);
Book book02 = new Book("ABC", "Test02", 3333.55D);
Book book03 = new Book("~!@", "Test02", 5555.5D);
ObservableList books = FXCollections.observableArrayList();
InvalidationListener listInvalidatedEvent = new ListInvalidatedEvent();
ListChangeListener listChangeListener = new ListChangeEvent();
books.addListener(listInvalidatedEvent::invalidated);
books.addListener(listChangeListener::onChanged);
books.addAll(book01, book02, book03);
// books.addListener(listInvalidatedEvent::invalidated);
// books.addListener(listChangeListener::onChanged);
book01.setPrice(22.3d);
books.remove(1);
}
}
测试结果:
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&调用集合Invalidated方法
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&调用集合Invalidated方法
打印集合中所有元素信息:
Test01, 123, 22.55
Test02, ABC, 3333.55
Test02, ~!@, 5555.5
集合中元素个数:3
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&调用集合Invalidated方法
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&调用集合Invalidated方法
】】】】】】】】】】】】】】】】】调用集合onChanged方法
········································调用Invalidated方法
Price: 22.3
········································调用Invalidated方法
调用Changed方法+++++++++++++++++++++++++++++++++++
Price: 22.3
调用Changed方法+++++++++++++++++++++++++++++++++++
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&调用集合Invalidated方法
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&调用集合Invalidated方法
打印集合中所有元素信息:
Test01, 123, 22.3
Test02, ~!@, 5555.5
集合中元素个数:2
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&调用集合Invalidated方法
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&调用集合Invalidated方法
】】】】】】】】】】】】】】】】】调用集合onChanged方法
Process finished with exit code 0
注意,如果两个事件注册在添加元素之后,则集合添加元素的导致集合失效(Invalidated)、变化(onChanged)事件不会触发。
如果只是改变集合中元素数据,则只会调用元素绑定的事件,而不会调用集合绑定的事件。
反过来,只改变集合中元素,但是元素本身数据不改变,则只调用集合绑定的事件,不会调用元素自身绑定的事件。
注意: