JavaFX检查是否正在侦听Node属性

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaFX检查是否正在侦听Node属性相关的知识,希望对你有一定的参考价值。

我有一个方法可以在某个Node属性上添加一个侦听器,在执行过程中,该方法可能会被调用多次,这将为该Node属性添加另一个(但相同的)侦听器,因此我尝试删除添加另一个监听器之前,请先避免监听器重复,例如:

myProperty.removeListener(this::method);
myProperty.addListener(this::method);

这看起来是正确的,但是这里的问题是,在删除之前,我必须检查该属性当前没有侦听器,类似这样的东西:

if(myProperty.hasListener(this::method)) //

但是这似乎不存在,然后如何检查是否正在侦听Node属性?

谢谢。

[[编辑:已解决]

removeListener(ChangeListener)方法不会导致错误,即使侦听器不存在。

答案

只是为了好玩(不推荐):

import javafx.application.Application;
import javafx.beans.property.*;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.stage.Stage;

import java.lang.reflect.Field;

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception{

        ChangeListener changeListener = new ChangeListener() {
            @Override
            public void changed(ObservableValue observable, Object oldValue, Object newValue) {

            }
        };
        SimpleBooleanProperty simpleBooleanProperty = new SimpleBooleanProperty();
        System.out.println(hasListener(simpleBooleanProperty,changeListener));
        simpleBooleanProperty.addListener(changeListener);
        System.out.println(hasListener(simpleBooleanProperty,changeListener));
        simpleBooleanProperty.removeListener(changeListener);
        System.out.println(hasListener(simpleBooleanProperty,changeListener));
    }

    public static boolean hasListener(ObservableValue observableValue, ChangeListener listener){

        Object value;
        ChangeListener[] list=null;
        ChangeListener changeListener=null;
        Field field = null;

        try {
            if(observableValue instanceof SimpleFloatProperty){
                field = FloatPropertyBase.class.getDeclaredField("helper");
            }
            else if(observableValue instanceof SimpleBooleanProperty){
                field = BooleanPropertyBase.class.getDeclaredField("helper");
            }
            else if(observableValue instanceof SimpleIntegerProperty){
                field = IntegerPropertyBase.class.getDeclaredField("helper");
            }
            field.setAccessible(true);
            value = field.get(observableValue);
            try {
                if(value==null){
                    return false;
                }
                field = value.getClass().getDeclaredField("listener");
                field.setAccessible(true);
                changeListener =(ChangeListener)field.get(value);
            }catch (NoSuchFieldException e) {
                //e.printStackTrace();
            }
            try {
                field = value.getClass().getDeclaredField("changeListeners");
                field.setAccessible(true);
                list =(ChangeListener[])field.get(value);
            }catch (NoSuchFieldException e) {
                //e.printStackTrace();
            }
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        if(list!=null){
            for (ChangeListener c:list) {
                if(c==listener){
                    return true;
                }
            }
            return false;
        }
        else {
            return changeListener==listener;
        }
    }
    public static void main(String[] args) {
        launch(args);
    }
}

输出:

false
true
false

更合理的方法:使用地图或标志。

顺便说一句:

如果根本没有侦听器,您也可以删除,因此您无需在删除之前进行检查enter image description here

以上是关于JavaFX检查是否正在侦听Node属性的主要内容,如果未能解决你的问题,请参考以下文章

JavaFX 属性删除侦听器不起作用

如何以毫秒为单位获取javaFX音频片段的长度[关闭]

尝试在片段中实现 OnClick 侦听器 [重复]

JavaFX UI 在事件侦听器中的 JavaFX 应用程序线程中冻结,但可与 Platform.runLater 一起使用

从父片段到选项卡片段的接口侦听器不起作用

JavaFX - 属性“无效”的含义