简体   繁体   English

Java ActionListeners

[英]Java ActionListeners

I am going to be developing a game in Java, and it will have many listeners( action, key, mouse, etc..). 我将用Java开发一个游戏,它将拥有许多听众(动作,键,鼠标等)。

My Question is what is the preferable way to implement the listeners. 我的问题是实现监听器的最佳方式。

Method 1: 方法1:

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

Method 2: 方法2:

create a new class(or multiple classes) which will implement ActionListener and have the methods for the different Game Componenets (buttons, movement, whatever else needs an ActionListener) 创建一个新类(或多个类),它将实现ActionListener并具有不同Game Componenets的方法(按钮,移动,其他任何需要ActionListener)

So, for instance. 所以,例如。 If I am making a button is it better to do 如果我正在制作一个按钮,那就更好了

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

});

or 要么

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");
        }
    }
}

I can see advantages in both ways, Method 1 you can see what is happening to that object directly, but method 2 you can see all components. 我可以从两个方面看到优势,方法1你可以直接看到该对象发生了什么,但方法2你可以看到所有组件。

So when developing large scale applications, which is easier to maintain, having all listeners in separate classes, or using Method 1? 那么在开发更容易维护的大规模应用程序时,将所有侦听器放在不同的类中,还是使用方法1?

Personally, I would prefer many Listeners to one with "if" checks. 就个人而言,我更倾向于使用“if”检查的许多听众。 It would allow me to modify them independently. 它允许我独立修改它们。

I would embed that code inside the UI. 我会将该代码嵌入UI中。 I'd write them as separate classes and inject them as dependencies using constructor or DI factory. 我将它们作为单独的类编写,并使用构造函数或DI工厂将它们作为依赖项注入。

Constructor injection: 构造函数注入:

public class YourPanel extends JPanel {
    private JButton button;

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

First, terms. 第一,条款。 In both cases you are defining classes, but in the first one they are called anonymous inner classes . 在这两种情况下,您都在定义类,但在第一种情况下,它们被称为匿名内部类 You will find some file like MyClass$1.java . 你会发现一些像MyClass$1.java这样的文件。

In that sense, MY (other may differ) rules would be 从这个意义上说,我的(其他可能不同的)规则就是

1) Use anonymous inner classes only for simpler actions that are not reused. 1)仅对不重用的简单操作使用匿名内部类。 For all the other, use "regular" classes. 对于所有其他人,使用“常规”类。

2) Reuse components only when they make sense. 2)只有在有意义的情况下才重新使用组件。 If you have two buttons that have wildly different meanings, don't try to reuse the same listener. 如果您有两个具有截然不同含义的按钮,请不要尝试重用相同的侦听器。 Create several ones. 创建几个。 By example, if you have two buttons (an increment and a decrement) you can reuse the same class since operation will be very similar. 例如,如果您有两个按钮(递增和递减),则可以重复使用相同的类,因为操作将非常相似。 If you have several values with such buttons, reuse the classes passing the object to be modified in the constructor. 如果您有多个具有此类按钮的值,请重用在构造函数中传递要修改的对象的类。 But do not mix a button to increment a value with a "start round" button. 但是不要混合使用“开始圆”按钮增加值的按钮。


UPDATE: 更新:

And, by the way, when you say: 顺便说一下,当你说:

I can see advantages in both ways, Method 1 you can see what is happening to that object directly, but method 2 you can see all components. 我可以从两个方面看到优势,方法1你可以直接看到该对象发生了什么,但方法2你可以看到所有组件。

It may look like an advantage to see all components but makes encapsulating the logic way more difficult, if all of your classes can change all of the other. 如果您的所有类都可以更改所有其他类,那么查看所有组件但使封装逻辑方式更加困难可能看起来更有优势。 Encapsulation means some extra work but in the end you get a product that's more maintanable, and that is an important thing. 封装意味着一些额外的工作,但最终你得到的产品更加可维护,这是一件很重要的事情。

Just to add one more stick to this fire, myself, I prefer to use AbstractActions, either as an anonymous inner class, or more often as an independent stand-alone class: 为了给这个火添加一个棒,我自己,我更喜欢使用AbstractActions,或者作为一个匿名的内部类,或者更常见的是作为一个独立的独立类:

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

As an example, a Control class that is part of an MVC Swing project of mine has this as part of its code: 作为示例,作为我的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;
   }

   // .....
}

And the abstract class that underlies all of my AbstractActions looks like so: 而作为我所有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();
   }

}

One caveat: Note that I'm not a professional programmer but rather a hobbiest, and so while my ideas work for me, they may not represent the absolute best in the field. 一个警告:请注意,我不是一个专业的程序员,而是一个最愚蠢的人,所以虽然我的想法对我有用,但他们可能并不代表该领域的绝对最佳。 All corrections and advice are most welcome. 所有的更正和建议都是最受欢迎的。 A weakness to my design above is that I think that I'm "injecting" my Actions in a clumsy way. 我上面设计的一个弱点是,我认为我是以笨拙的方式“注入”我的动作。

I would honestly prefer the first one. 老实说,我更喜欢第一个。 you're right the first approach you can easily see what's going on that Component. 你是对的第一种方法,你可以很容易地看到该组件正在发生什么。 However. 然而。 there will be times where a button will probably have the same behavior or same ActionListener, that being said I would prefer the approach 2. so you can easily reuse actionListeners. 有时按钮可能会有相同的行为或相同的ActionListener,据说我更喜欢方法2.所以你可以轻松地重用actionListeners。

You could also take a look at this swing framework called swingobjects that i have been working on. 您还可以看看我一直在研究的名为swingobjects的摇摆框架。

https://github.com/Sethuraman/swingobjects https://github.com/Sethuraman/swingobjects

If you create a Jframe using the FrameFactory class, swingobjects will register a GlobalListener for you for all the widgets you have declared in your frame. 如果使用FrameFactory类创建Jframe,swingobjects将为您在框架中声明的所有小部件注册GlobalListener。 What this allows you to do is, mark a method in your frame with an annotation like this: 这允许您做的是,使用如下注释在框架中标记方法:

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

The GlobalListener will call this method via reflection. GlobalListener将通过反射调用此方法。 This means, you will not have to write if blocks, create anonymous inner classes. 这意味着,您不必编写if块,创建匿名内部类。 Everything is transparently handled for you. 一切都是透明处理的。 Take a look at the framework ... 看看框架......

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM