【问题标题】:Java Event Listener to detect a variable change用于检测变量更改的 Java 事件侦听器
【发布时间】:2012-01-05 02:00:30
【问题描述】:

我似乎无法在任何地方找到我的问题的答案。是否有任何事件侦听器可以检测布尔值或其他变量的变化然后对其进行操作。或者是否可以创建一个自定义事件侦听器来检测这一点?

我似乎无法在任何地方找到解决方案,我发现 this website 解释了如何创建自定义事件

【问题讨论】:

    标签: java boolean


    【解决方案1】:

    就像您需要创建一个事件侦听器一样,您还需要创建事件触发器——因为没有什么可以为您自动执行此操作。我提供了示例代码,向您展示了如何实现这样的 firer。

    这个测试实现并不完美。它只包括一种添加侦听器的方法。您可能希望包含一种方法来删除不再对接收事件感兴趣的侦听器。另请注意,此类不是线程安全的。

    import java.util.List;
    import java.util.ArrayList;
    import java.util.EventListener;
    import java.util.EventObject;
    import java.awt.EventQueue; 
    
    /**
     * This class uses the EventQueue to process its events, but you should only 
     * really do this if the changes you make have an impact on part of a GUI 
     * eg. adding a button to a JFrame.
     *
     * Otherwise, you should create your own event dispatch thread that can handle
     * change events
     */
    public class BooleanChangeTest implements BooleanChangeDispatcher {
    
        public static void main(String[] args) {
    
            BooleanChangeListener listener = new BooleanChangeListener() {
                @Override
                public void stateChanged(BooleanChangeEvent event) {
                    System.out.println("Detected change to: "
                        + event.getDispatcher().getFlag()
                        + " -- event: " + event);
                }
            };
    
            BooleanChangeTest test = new BooleanChangeTest(false);
            test.addBooleanChangeListener(listener);
    
            test.setFlag(false); // no change, no event dispatch
            test.setFlag(true); // changed to true -- event dispatched
    
        }
    
        private boolean flag;
        private List<BooleanChangeListener> listeners;
    
        public BooleanChangeTest(boolean initialFlagState) {
            flag = initialFlagState;
            listeners = new ArrayList<BooleanChangeListener>();
        }
    
        @Override   
        public void addBooleanChangeListener(BooleanChangeListener listener) {
            listeners.add(listener);
        }
    
        @Override
        public void setFlag(boolean flag) {
            if (this.flag != flag) {
                this.flag = flag;
                dispatchEvent();
            }
        }
    
        @Override
        public boolean getFlag() {
            return flag;
        }
    
        private void dispatchEvent() {
            final BooleanChangeEvent event = new BooleanChangeEvent(this);
            for (BooleanChangeListener l : listeners) {
                dispatchRunnableOnEventQueue(l, event);
            }
        }
    
        private void dispatchRunnableOnEventQueue(
                    final BooleanChangeListener listener, 
                    final BooleanChangeEvent event) {
    
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    listener.stateChanged(event);
                }
            });
        }
    
    }
    
    interface BooleanChangeDispatcher {
    
        public void addBooleanChangeListener(BooleanChangeListener listener);
        public boolean getFlag();
        public void setFlag(boolean flag);
    
    }
    
    /**
     * Listener interface for classes interested in knowing about a boolean
     * flag change.
     */
    interface BooleanChangeListener extends EventListener {
    
        public void stateChanged(BooleanChangeEvent event);
    
    }
    
    /** 
     * This class lets the listener know when the change occured and what 
     * object was changed.
     */
    class BooleanChangeEvent extends EventObject {
    
        private final BooleanChangeDispatcher dispatcher;
    
        public BooleanChangeEvent(BooleanChangeDispatcher dispatcher) {
            super(dispatcher);
            this.dispatcher = dispatcher;
        }
    
        // type safe way to get source (as opposed to getSource of EventObject
        public BooleanChangeDispatcher getDispatcher() {
            return dispatcher;
        }
    }
    

    【讨论】:

    • 谢谢你这工作完美!现在只需了解它的所有内容并对其进行调整以适应我想做的事情。谢谢。
    【解决方案2】:

    使用PropertyChangeSupport。您不必实现那么多,它是线程安全的。

    public class MyClassWithText {
        protected PropertyChangeSupport propertyChangeSupport;
        private String text;
    
        public MyClassWithText () {
            propertyChangeSupport = new PropertyChangeSupport(this);
        }
    
        public void setText(String text) {
            String oldText = this.text;
            this.text = text;
            propertyChangeSupport.firePropertyChange("MyTextProperty",oldText, text);
        }
    
        public void addPropertyChangeListener(PropertyChangeListener listener) {
            propertyChangeSupport.addPropertyChangeListener(listener);
        }
    }
    
    public class MyTextListener implements PropertyChangeListener {
        @Override
        public void propertyChange(PropertyChangeEvent event) {
            if (event.getPropertyName().equals("MyTextProperty")) {
                System.out.println(event.getNewValue().toString());
            }
        }
    }
    
    public class MyTextTest {
        public static void main(String[] args) {
            MyClassWithText interestingText = new MyClassWithText();
            MyTextListener listener = new MyTextListener();
            interestingText.addPropertyChangeListener(listener);
            interestingText.setText("FRIST!");
            interestingText.setText("it's more like when you take a car, and you...");
        }
    }
    

    【讨论】:

    • 谢谢。我为布尔变量做的。
    【解决方案3】:

    你也可以尝试实现一个观察者。

    首先创建可观察对象:

    import java.util.Observable;
    
    public class StringObservable extends Observable {
     private String name;
    
    
     public StringObservable(String name) {
      this.name = name;
     }
    
     public String getName() {
      return name;
     }
    
    
     public void setName(String name) {
      this.name = name;
      setChanged();
      notifyObservers(name);
     }
    
    }
    

    然后是观察者:

    import java.util.Observable;
    import java.util.Observer;
    
    public class NameObserver implements Observer {
     private String name;
    
     public NameObserver() {
      name = null;
     }
    
     public void update(Observable obj, Object arg) {
      if (arg instanceof String) {
       name = (String) arg;
       System.out.println("NameObserver: Name changed to " + name);
      } else {
       System.out.println("NameObserver: Some other change to subject!");
      }
     }
    }
    

    在你的主要(或其他任何地方):

    public class TestObservers {
     public static void main(String args[]) {
    
      // Create the Subject and Observers.
      StringObservable s = new StringObservable("Test");
      NameObserver nameObs = new NameObserver();
    
      // Add the Observer
      s.addObserver(nameObs);
    
    
      // Make changes to the Subject.
      s.setName("Test1");
      s.setName("Test2");
     }
    }
    

    大多是here

    【讨论】:

    • 注意:Java.util.observable 现在似乎已被弃用。
    【解决方案4】:

    回答很晚,但这是一个可以通过 Observer/Observable 解决的问题。 Example

    【讨论】:

      【解决方案5】:

      您设置的布尔值应该只允许通过 setter 方法执行,例如:

      public void setFlag(boolean flag){
          //Method code goes here
      }
      

      现在在 now set 方法中,您可以根据传入的值、需要触发的事件来决定。我用简单的术语解释,没有引入复杂的术语,所以你可以更好地理解,所以代码 sn-p 看起来像:

      public void setFlag(boolean flag){
      
          //if flag is TRUE do something
          //If flag is FALSE then do something 
      
          //And finally do what you needed to do with flag
      }
      

      如果您需要更多信息,请提出问题

      【讨论】:

      • 这是否会不断检测和感知变化的时刻?还是只运行一次?
      • 这适用于任何时候通过 setter 更改布尔值。
      【解决方案6】:

      当您想要侦听 I/O 更改时,您可以创建一个侦听器。主要在图形上。 您的问题的答案是保持运行程序的状态,然后检查变量是否从程序无限循环内的状态发生变化。

      【讨论】:

      • 你的意思是像创建一个计时器或循环来检测何时发生这种变化?这就是我试图避免做的事情,因为当同时运行太多时,可能会导致大型程序出现延迟。
      • 好吧..这取决于您的设计。另外你总是可以使用线程,但是你应该注意同步对象,否则你会得到一个并发修改异常
      【解决方案7】:

      您可以为此使用 AOP,也许是 AspectJ?查看几个示例here(如果您使用 Eclipse,那么通过他们的插件使用 AspectJ 非常简单)。

      对你来说,你会有一个类似于 SampleAspect 中使用的切入点,但只有当有人对布尔变量进行新的 SET 时才会使用这个切入点(这并不意味着值已经改变,只是有人将值加载到变量中)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-08-17
        • 2021-10-11
        • 1970-01-01
        • 1970-01-01
        • 2014-10-07
        • 2019-06-04
        • 2010-10-04
        相关资源
        最近更新 更多