JavaFX学习:ObservableList/ObservableSet/ObservableMap的invalidated事件和changed事件

105 篇文章 5 订阅

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事件。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
NoClassDefFoundError:javafx/scene/Parent是一个Java运行时异常,当JVM发现一个类加载器尝试加载名为javafx.scene.Parent的类时,在当前的类加载器树中找不到该类时,就会抛出此异常。这个异常表示在运行时无法找到该类的定义。 要解决这个问题,有几种可能的原因和解决方案: 1. 缺少JavaFX库: NoClassDefFoundError:javafx/scene/Parent可能是因为缺少JavaFX库所致。在Java 11之后,JavaFX已经从JDK中移除,如果你使用的是Java 11或更高版本,你需要单独引入JavaFX库。你可以从OpenJFX官方网站下载并添加到你的项目中。 2. 类加载器问题: 这个异常也可能是由于类加载器的问题引起的。当你的应用程序的类加载器无法找到所需的类时,就会出现NoClassDefFoundError。你可以检查你的类路径设置,确保所有必需的依赖项都包含在其中。 3. 版本兼容性问题: NoClassDefFoundError也可能是由于版本兼容性问题引起的。如果你的应用程序依赖于某个特定的JavaFX版本,而你的运行环境中安装了不兼容的JavaFX版本,就可能会出现这个异常。你需要确保你的运行环境中安装的JavaFX版本与你的应用程序所需的版本相匹配。 总结起来,要解决NoClassDefFoundError:javafx/scene/Parent异常,你可以检查是否缺少JavaFX库,检查类加载器设置,以及确保版本兼容性。根据具体情况采取相应的解决方案。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值