17

What's the best way for implementing the java.awt.event.ActionListener interface?

Have your class implement ActionListener and add this as an ActionListener:

class Foo implements ActionListener{

    public Foo() {
        JButton button = new JButton();
        button.addActionListener(this);
    }

    public void actionPerformed(ActionEvent e) {

    }
}

Or add an object of an anonymous ActionListener class:

class Foo{

    public Foo() {
        JButton button = new JButton();
        button.addActionListener(new ActionListener() {     
            public void actionPerformed(ActionEvent e) {

            }
        });
    }
}
Raedwald
  • 40,290
  • 35
  • 127
  • 207
elias
  • 12,880
  • 4
  • 33
  • 62

3 Answers3

30

Some (jeanette/kleopatra) say to almost never use ActionListener, and to instead use Actions such as an AbstractAction. It's almost always a bad ideal to have your GUI class implement your listeners though as this breaks the Single Responsibility Principle and makes your code more difficult to maintain and extend,and so I strongly urge you not to do that.

So for example, an inner class for this:

import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;

class Foo {

   public Foo() {
       JButton button = new JButton(new ButtonAction("Action", KeyEvent.VK_A));
   }

   private class ButtonAction extends AbstractAction {
      public ButtonAction(String name, Integer mnemonic) {
         super(name);
         putValue(MNEMONIC_KEY, mnemonic);
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         System.out.println("button pressed");
      }
   }

}
Hovercraft Full Of Eels
  • 276,051
  • 23
  • 238
  • 346
  • +1 For `AbstractAction` and [`Single Responsibility Principle`](http://en.wikipedia.org/wiki/Single_responsibility_principle). – Eng.Fouad Jul 11 '12 at 17:56
  • 1
    Nice, but it seems to be more complex (in code maintaining terms), and more difficult to read. Or I'm wrong? – elias Jul 11 '12 at 17:57
  • It gets easy to read as you get more familiar with it. I've used it when I've tried to maintain a well separated MVC pattern, and have had my Control inject Actions into my JButtons. – Hovercraft Full Of Eels Jul 11 '12 at 17:58
  • 2
    And don't forget, easier to test. You can simply test the action class when it is not tied to your UI – Robin Jul 11 '12 at 21:40
  • 1
    Related example—and constructive review in comments—[here](http://stackoverflow.com/a/11372932/230513). – trashgod Jul 11 '12 at 22:27
  • @HovercraftFullOfEels how do you manage the dependencies when an Action is used by 2 different Controllers ? Would you create separate actions ? (I understand the goal is to use the same action in different contexts) And, I may need knowledge about my view or my controller. I had created Actions used in different controllers but had serious dependencies problems so went back to inner class in the view – Rytek Apr 23 '14 at 16:56
8

The second option (anonymous class) is certainly better, another option would be to have a nested class within Foo.

I wouldn't go with the first option for two reasons:

  • The users of Foo shouldn't have to know that it implements ActionListener.
  • You cannot implement two different listeners in the same class.
casablanca
  • 66,266
  • 7
  • 126
  • 145
  • I would upvote this answer for the first reason, but the second reason is just wrong imho. You can check the source of the `ActionEvent` and decide the code path you should take. Whether that is an elegant solution is another discussion, but it is certainly possible – Robin Jul 11 '12 at 21:42
  • 4
    @Robin: You're right but that was not my point. What I meant is that one wouldn't be able to implement the `ActionListener` twice in the same class. – casablanca Jul 12 '12 at 04:14
4

It depends. If you want to reuse the ActionListener across multiple components, option one is better. If the ActionListener will only ever be associated with the one button, option two is fine.

Generally, you would create a separate class (or inner class), if you anticipate some growth in the project. There's no need for Foo to implement ActionListener.

SpaceCore186
  • 586
  • 1
  • 8
  • 20
Rob Wagner
  • 4,285
  • 13
  • 24
  • 2
    Having a gui class implement ActionListener is only for toy programs. Since he's asking about "best practices" then there is no use of this in any circumstances. – Hovercraft Full Of Eels Jul 11 '12 at 19:05