Java ActionListeners

时间:2013-06-01 23:45:12

标签: java swing jbutton actionlistener anonymous-inner-class

我将用Java开发游戏,它将拥有许多听众(动作,键,鼠标等)。

我的问题是实现听众的最佳方式。

方法1:

this.addActionListener(new ActionListener() {
   // Overide methods go here
});

方法2:

创建一个新类(或多个类),它将实现ActionListener并具有不同Game Componenets的方法(按钮,移动,其他任何需要ActionListener的方法)

所以,例如。如果我正在制作按钮,那么最好做

JButton button = new JButton();
button.addActionListener(new ActionListener() {

});

JButton button = new JButton();
button.addActionListener(new MyActionListener());

// MyActionListener
class MyActionListener implements ActionListener {
    @Override
    public void actionPerformed(ActionEvent e) {
        Object objectPressed = e.getSource();
        if(objectPressed.equals(button) {
          System.out.println("Hello World");
        }
    }
}

我可以从两个方面看到优势,方法1你可以直接看到该对象发生了什么,但方法2你可以看到所有组件。

那么在开发更容易维护的大规模应用程序时,将所有侦听器放在不同的类中,还是使用方法1?

5 个答案:

答案 0 :(得分:3)

就个人而言,我更倾向于使用“if”检查的听众。它允许我独立修改它们。

我会将该代码嵌入UI中。我将它们作为单独的类编写,并使用构造函数或DI工厂将它们作为依赖项注入。

构造函数注入:

public class YourPanel extends JPanel {
    private JButton button;

    public YourPanel(ActionListener buttonListener) {
        this.button = new JButton("Do It");
        this.button.addActionListener(buttonListener);
    }
}

答案 1 :(得分:2)

首先,条款。在这两种情况下,您都在定义类,但在第一种情况下,它们被称为匿名内部类。你会发现一些文件,如MyClass$1.java

从这个意义上讲,我的(其他可能不同的)规则将是

1)仅对未重复使用的简单操作使用匿名内部类。对于所有其他人,使用“常规”类。

2)只有在有意义的情况下才重新使用组件。如果您有两个具有截然不同含义的按钮,请不要尝试重用相同的侦听器。创建几个。例如,如果您有两个按钮(递增和递减),则可以重复使用相同的类,因为操作将非常相似。如果您有多个具有此类按钮的值,请重用在构造函数中传递要修改的对象的类。但是不要混合使用“开始回合”按钮增加值的按钮。


<强>更新

顺便说一下,当你说:

  

我可以从两个方面看到优势,方法1你可以直接看到该对象发生了什么,但方法2你可以看到所有组件。

如果您的所有类都可以更改所有其他类,那么查看所有组件但使封装逻辑方式更加困难可能看起来更有优势。 封装意味着一些额外的工作,但最终你得到的产品更加可维护,这是一件很重要的事情。

答案 2 :(得分:2)

为了再添加一个棒,我自己,我更喜欢使用AbstractActions,或者作为一个匿名的内部类,或者更常见的是作为一个独立的独立类:

JButton myExitButton = new JButton(new MyExitAction());

作为示例,作为我的MVC Swing项目的一部分的Control类将此作为其代码的一部分:

public class Control {

   // these two types below are interfaces
   private Model model;
   private View view;

   public Control(Model model, View view) {
      this.model = model;
      this.view = view;

      addViewListeners();
   }

   private void addViewListeners() {
      view.setGetPageAction(new GetPageAction(this, "Get Page", KeyEvent.VK_G));
      view.setSetTnRendererBtnAction(new SetTnRendererBtnAction(this, "Show Images", KeyEvent.VK_S));
      view.setClearThumbNailsAction(new ClearThumbNailsAction(this, "Clear ThumbNails", KeyEvent.VK_C));
      view.setSetDestinationAction(new SetDestinationAction(this, "Set Destination", KeyEvent.VK_T));
      view.setDownloadAction(new DownloadAction(this, "Download", KeyEvent.VK_D));
      view.setExitAction(new ExitAction(this, "Exit", KeyEvent.VK_X));
      model.addPropertyChangeListener(new ModelListener());
   }

   public View getView() {
      return view;
   }

   public Model getModel() {
      return model;
   }

   // .....
}

作为我所有AbstractActions基础的抽象类看起来像这样:

public abstract class MyAbstractAction extends AbstractAction {

   protected Control control;
   protected Model model;
   protected View view;

   public MyAbstractAction(Control control, String txt, int mnemonic) {
      super(txt);
      putValue(MNEMONIC_KEY, mnemonic);
      this.control = control;
      this.model = control.getModel();
      this.view = control.getView();
   }

}

一个警告:请注意,我不是一个专业的程序员,而是一个嗜好的人,所以虽然我的想法对我有用,但他们可能并不代表该领域的绝对最佳。所有的更正和建议都是最受欢迎的。我上面设计的一个弱点是,我认为我是以笨拙的方式“注入”我的动作。

答案 3 :(得分:0)

老实说,我更喜欢第一个。你是对的第一种方法,你可以很容易地看到该组件正在发生什么。然而。有时按钮可能会有相同的行为或相同的ActionListener,据说我更喜欢方法2.所以你可以轻松地重用actionListeners。

答案 4 :(得分:0)

您还可以看看我一直在研究的名为swingobjects的摇摆框架。

https://github.com/Sethuraman/swingobjects

如果使用FrameFactory类创建Jframe,swingobjects将为您在框架中声明的所有小部件注册GlobalListener。这允许您做的是,使用如下注释标记框架中的方法:

@Action("<action name or button text>")
public void performAction(ActionEvent evt){
....
}

GlobalListener将通过反射调用此方法。这意味着,您不必编写if块,创建匿名内部类。一切都是透明处理的。看看框架......