【问题标题】:JavaFX check if a Node property is being listenedJavaFX 检查是否正在侦听 Node 属性
【发布时间】:2020-05-25 02:55:22
【问题描述】:

我有一个向某个 Node 属性添加侦听器的方法,在执行过程中,该方法可能会被多次调用,这会向该 Node 属性添加另一个(但相同的)侦听器,所以我尝试在添加另一个侦听器之前删除侦听器以避免这样的重复:

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

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

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

但是这个好像不存在,那么如何判断一个Node属性是否被监听呢?

谢谢。

[编辑:已解决]

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

【问题讨论】:

  • hmm .. 不完全确定第一个会做你想做的事 - 你测试过吗?无论如何,没有 api 可以检查注册的侦听器,您必须自己实现它(通过标志,对侦听器的引用等)
  • 不太明白为什么你要多次添加同一个监听器..听起来像次优逻辑/设置
  • 你可能想看看这个:stackoverflow.com/questions/37162216/…
  • @kleopatra,为了简单起见,我在不同的选项卡中有很多 textarea,还有一个包含当前 textArea 的变量,这个变量会根据所选的 textArea 发生变化,这就是为什么我必须多次添加一个监听器.但无论如何,我写的第一个代码工作正常,我担心 remove 方法会导致错误,但即使根本没有监听器,它似乎也能工作。所以我想问题解决了:)
  • 不知道你的意思是 working .. 但是像在你的第一个 sn-p 中那样删除监听器 不会 删除它,它是仍然注册并做它应该做的任何事情;)再次:更改您的应用程序设计,以便您可以跟踪您正在侦听的属性并添加/删除侦听器(存储在字段与方法句柄中)

标签: java javafx listener


【解决方案1】:

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

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

更合理的方法:使用地图或旗帜。

顺便说一句:

如果根本没有侦听器,您也可以删除,因此您无需在删除前检查

【讨论】:

  • 我刚刚注意到你说的移除监听器,我担心它会导致错误,但我猜我错了,也感谢代码,它很聪明!
  • 为解决(很可能)损坏的应用程序设计工作带来了很多麻烦;)但是..我们为了好玩而做的事情
猜你喜欢
  • 1970-01-01
  • 2015-06-16
  • 1970-01-01
  • 1970-01-01
  • 2011-11-29
  • 2019-05-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多