Best way to implement actionPerformed?

In Java, we have two ways to implement actionPerformed:

  • One actionPerformed method for each class: use if-else to check the source of the event;
  • Use anonymous inner classes and implement the actionPerformed method in the place where this object is created;

For option 1, it's easy to track where the actionPerformed code is, because there is only one method for each class. We can easily find this method, and then look inside to find the code we are looking for. However, there may be too many if-else statements if we have many listeners for actions.

For option 2, it is not easy to find where the actionPerformed code is because it is scattered throughout the class. If you have a lot of action listeners, it will be more difficult to keep track of actionPerformed instances.

I personally prefer option 1, because it’s much easier to maintain the code, even performance may be less efficient than option 2.

What are the pros and cons of each method? What else should be considered when choosing how to implement actionPerformed? Which way do you prefer?

EDIT:

therefore, there is a third option based on the assumption from A. Lee below. this is a combination of option 1 and option 2: using anonymous inner classes, but sharing them in ONE place in the class. I think it is a good idea.

+4
source share
4 answers

I think the long if-else chain in the actionPerformed method is ugly for several reasons: each time you do unnecessary checks to determine which receiver code is for the ActionEvent , and as the code grows, it becomes more inaccessible.

If you want all your action handlers to be in the same place, use the initializeActionListeners method, which associates your ActionListeners with your controls. Or bind them where you initialize them so that the event handler is closer to your widget / control itself, for example,

 // not thread-safe private JLabel getSomeLabel() { if (someLabel == null) { someLabel = new JLabel("Some label, huh"); someLabel.addActionListener(...) } return someLabel; } 
+3
source

Incorrect alternatives: the question is not an anonymous class compared to the long large if-else construct (you can easily get the latter in the first). The question is whether there should be a semantically strong class (anonymous or not) that does exactly one job, is the only one that does this and does it completely. After all, we are on OO earth; -)

So: strict no-no-ever for if-then-else structures.

+1
source

I use the third option, I wrote my own manager, which associates methods with JButtons directly through annotations.

I provide it as an OpenSource project, you can check it out at https://github.com/MarkyVasconcelos/Towel/wiki/ActionManager

The upside is that you don’t need to implement any ActionListener or use Anonymous inner classes.

All actions relate to the methods of your class.

0
source

In most cases there is not much difference to offer one over the other.

I would say: if the cases are similar, put them together, but only to name the appropriate method:

  public void actionPerformed (ActionEvent e) { String cmd = e.getActionCommand (); if (cmd.equals (cmdNextPage)) nextPage (); else if (cmd.equals (cmdLastPage)) lastPage (); else if (cmd.equals (cmdOk)) ok (); // ... and so on 

Thus, you can easily and simply call methods, regardless of the event, perhaps from the scope of testing or to cancel / redo. Obviously, the overall picture is obvious.

In very rare cases, you may be interested in not registering individual events and sources independently. Then one listener on an ActionEvent seems more appropriate.

From the point of view of pure OOP, I think that one listener per button (for example) is more straightforward, and out of a desire to optimize the simulation I do not feel comfortable with 20 or 40 ActionListeners, but in my rational moments, I do not believe that 40 ActionListeners have noticeable effect. But they clutter up your file system, your IDE browser, so I guess there is a reasonable reason in the end to reduce the number of listeners.

The regular receiver is easy to use with the factory button:

  private void addButton (JPanel jp, String cmd, String ttt) { JButton jb = new JButton (cmd); jb.setToolTipText (ttt); jp.add (jb); jb.addActionListener (this); buttonlist.add (jb); } /** @return a Panel with Action-Buttons. */ private JPanel createControlPanel () { JPanel m = new JPanel (); m.setLayout (new BoxLayout (m, BoxLayout.Y_AXIS)); JPanel jpc = new JPanel (); jpc.setLayout (new FlowLayout ()); buttonlist = new ArrayList <JButton> (); addButton (jpc, cmdLastPage, "last page"); addButton (jpc, cmdNextPage, "next page"); addButton (jpc, cmdOk, "save"); addButton (jpc, cmdEsc, "exit"); 

It is very easy and clear where to add a new button and how. I find it very convenient.

0
source

All Articles