【问题标题】:What is the common way to program action listeners?编写动作监听器的常用方法是什么?
【发布时间】:2010-03-12 16:55:39
【问题描述】:

我刚开始学习如何使用动作监听器。据我了解,它的工作方式如下:

  1. 有些类默认包含“addActionListener”方法(例如按钮类)。

  2. 使用此方法,我们将动作侦听器添加到对象。例如:listenedObject.addActionListener(listeningObject)

  3. 当执行带有“listenedObject”的动作时,将调用“listeningObject”的“actionPerformed”方法。所以,这意味着当我们为 listenerObject 编写一个类时,我们需要在其中放置“actionPerformed”方法。

我不清楚的是,我们是否应该为每个我们想要收听的对象创建一个新类。在我看来,这不是一个优雅的解决方案。另一方面,如果我们为所有(或至少许多)对象有一个动作侦听器类,那么我们就会遇到问题,因为此类的实例将不知道哪个对象正在调用“actionPerformed”方法(我们需要知道,因为 actionPerformed 执行的操作因调用此方法的人而异)。

在我看来,对于我们需要创建的每个监听对象都是“个人”动作监听器,我们可以通过为动作监听器的相应字段设置特定值来实现。但我不确定这是一种标准的方式吗?人们通常是怎么做的?

【问题讨论】:

    标签: java actionlistener


    【解决方案1】:

    从我个人的经验来看,最常见的处理方法是简单地创建一个匿名内联类。像这样:

    listenedObject.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent evt) {
            // Your action handling code in here
        }
    });
    

    我经常看到人们调用包含listenedObject 的对象的方法。例如,在具有按钮的 Dialog 中:

    myOkayButton.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent evt) {
            okayButtonPressed();
        }
    });
    

    然后在对话框类中:

    private void okayButtonPressed() {
        // Do what we need to do
    }
    

    【讨论】:

    • 好的。我懂了。顺便问一下,@Override 是什么意思?
    • 甚至:public void actionPerformed(ActionEvent e) { onMyButtonClicked();} - 几乎是一个方法指针
    • @Override 是一个注解,它意味着 Public void actionPerformed() 覆盖了其超类中的一个方法。当您创建这样的内联匿名类时,您将覆盖 ActionListener。你只是没有给它一个名字。
    • 注解只是告诉编译器在超类中寻找被覆盖的方法,如果它不存在或不匹配就对你大喊。
    • 您也可以调用 evt.getSource() 来获取引发事件的对象 - 这意味着您可以使用单个侦听器来侦听许多事件源上的事件...例如,这很常见在 JFrame 上设置侦听器来侦听该 JFrame 的许多控件的操作。
    【解决方案2】:

    就个人而言,如果可能的话,我更喜欢使用Action 类(例如AbstractAction 的子类),而不是简单地依赖动作监听器。这样,我可以为原始小部件提供名称、图标、工具提示等...

    【讨论】:

      【解决方案3】:

      我一直认为有用的方法(用于导航目的)是创建一个匿名内部类,然后委托给外部类:

      listenedObject.addActionListener(new ActionListener() {
          @Override
          public void actionPerformed(ActionEvent evt) {
              listenedObject_actionPerformed(evt);
          }
      });
      
      
      private void listenedObject_actionPerformed(ActionEvent evt) {
          //Your handling goes here
      }
      

      然后使用结构查找(IDEA 中的 CTRL+F12,Eclipse 中的 CTRL+O)在 IDE 中获取处理代码要容易得多。

      使用单个类(如 GUI MyCoolPanel)作为其一组组件(按钮等)的公共侦听器的问题在于,actionPerformed 方法与 if-else 有很多丑陋的比较弄清楚哪个按钮实际上被按下了——一点也不OO!

      你当然不应该过分担心这种事情的性能方面——它们可能在极端情况下可以忽略不计!过早的优化是出了名的坏事

      【讨论】:

        【解决方案4】:

        我一直认为有用的方法是创建一个单独的类,该类实现 ActionListener 接口和执行操作所需的所有其他方法。这样,动作就不会与特定对象绑定,并且可以从按钮、菜单等触发。我猜有点像Command pattern。它使代码保持简单。

        匿名类不可重用。

        重定向到包含 listeneredObject 的对象会导致难以维护的巨大类。

        【讨论】:

          【解决方案5】:

          请注意方法 removeActionListener 的存在是有原因的。如果您侦听的对象将与处理事件的对象一起死亡,您可以跳过侦听器清理。但是,如果您的组件侦听从外部源提供的模型,您应该在 addNotify 中添加您的侦听器并在 removeNotify 方法中删除它们。否则你可能会有内存泄漏。

          【讨论】:

            【解决方案6】:

            也许目前还没有,但我相信在不久的将来(Java 7 发布之后)这样的事情将是常见的方式:

            listenedObject.addActionListener ( #{doSmth();} );
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2021-07-02
              • 1970-01-01
              • 2016-10-09
              • 1970-01-01
              • 2011-11-28
              • 2014-06-11
              • 2013-07-10
              • 2021-12-18
              相关资源
              最近更新 更多