8


Sorry for the title, probably too generic.

I already read How to Write an Action Listener tutorial by Java and I already read this question, but I still have some doubts: I was wondering which solution is the best when I have to perform the same action multiple time.

I'd want to reuse the same ActionListener, but I am not sure on how to achieve this in the best way (speaking in term of: code readability, code mantainability, performance and code style).

First the "standard" code (which I would use if I'm not going to reuse the action listener):

btnMenu.addActionListener(
    new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            Navigator.showMenu();
        }
    }
);

This way I can't reuse anything obv, since it's an anonymous inner class...

Now, I can think of the following solutions:

  1. Store a reference of an Anonymous Inner Class in a field (that will most likely be static final);
  2. Write a new class that implements ActionListener interface.

Example code for solution 1:

public static final MENU_ACTION_LISTENER = new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        Navigator.showMenu();
    }
};

btnMenu.addActionListener(MENU_ACTION_LISTENER);

Example code for solution 2:

// package-private, only GUI-package classes should be able to use it.
// most likely I won't ever need to subclass it, so why not making it final?
final class MenuActionListener implements ActionListener  {
    public void actionPerformed(ActionEvent e) {
        Navigator.showMenu();
    }
}

// now, wherever I need to use it:
btnMenu.addActionListener(new MenuActionListener());

I have some doubts about both solutions:

  1. Where to store references to Anonymous Action Listeners? I could have a sort of utility class (e.g. ActionListenersUtil) where store all action listeners I want to reuse in static final fields, but I don't like it... it seems to me poor design.

  2. It makes more sense, probably best follows the Command Pattern... I initially had some doubt about the packages... I'd like to have all listeners in a separate package (e.g. com.myapp.gui for gui elements and com.myapp.gui.listeners for listeners. But when I wrote down this I realized that I have no choice: the only place where it make sense is in the same package (because they must be package-private), even if for the sake of order I would have like to put them all in a separate package. I still have some doubt though, because most action listeners may be reusable even in case GUI changes; it still would be a good idea to have it in the same package?

Another question: what's the difference between calling btnMenu.addActionListener(MENU_ACTION_LISTENER); and btnMenu.addActionListener(new MenuActionListener()); (speaking in term of JVM, class loading, class compiling, memory occupied by each class, garbage collection and so on)?

Please help, I'm so confused right now! :(

Community
  • 1
  • 1
kelo
  • 489
  • 1
  • 11
  • 20

1 Answers1

14

The best way is to create an Action instead of an ActionListener if you have to attach it to buttons, menus, ... . An Action is the model of a JButton, and the model is meant to be shared

This also gives you the ability to change the text, icon, enabled status, and other properties of all the buttons that the Action is attached to at the same time without multiple calls. Plus, it can be attached to menu items and such as well.

To create an Action you do not have to start from scratch. AbstractAction is a good starting point. The Swing Action tutorial is also a good read.

Robin
  • 36,233
  • 5
  • 47
  • 99
  • 3
    +1 This also gives you the ability to change the text, icon, enabled status, and other properties of all the buttons that the `Action` is attached to at the same time without multiple calls. Plus, it can be attached to menu items and such as well. – Brian Sep 17 '12 at 16:55
  • @Brian very good remark. I copy-pasted it in the answer to make it more complete – Robin Sep 17 '12 at 17:06
  • @Robin Thanks! Wish I could +1 twice. `Action` is one of the most underused classes in Swing, IMO. – Brian Sep 17 '12 at 17:10
  • oh shi-! I'm a little too late for that! :| Inexperience can do bad jokes... unfortunately now I cannot change everything, is there an elegant way to go with `ActionListener`s? – kelo Sep 18 '12 at 11:14