Roman
Roman

Reputation: 131208

What is the common way to program action listeners?

I just started to learn how to use action listeners. To my understanding it works in the following way:

  1. There are some classes which contains "addActionListener" method by default (for example classes for buttons).

  2. Using this method we add an action listener to an object. For example: listenedObject.addActionListener(listeningObject).

  3. When an action with the "listenedObject" is performed, the "actionPerformed" method of the "listeningObject" will be called. So, it means that when we program a class for the listeningObject, we need to put there "actionPerformed" method.

What is not clear to me, should we create a new class for every object that we want to listen. It does not seem to me as an elegant solution. On the other hand, if we have one action listener class for all (or at least many) object, than we have a problem since a instance of this class will not know which object is calling the "actionPerformed" method (and we need to know that since actions performed by the actionPerformed differs depending on who is called for this method).

In my opinion, for every listened object we need to create are "personal" action listener and we can do it by setting a specific value to the corresponding field of the action listener. But I am not sure that it is a standard way to go? How do usually people do it?

Upvotes: 5

Views: 10248

Answers (6)

Frank Ross
Frank Ross

Reputation: 349

The way I have always found useful is to create a separate class which implements the ActionListener interface and all the other methods necessary to carry the action. This way, an action is not tied to a specific object and can be triggered from a button, a menu, etc. A little bit like the Command pattern I guess. It keeps the code simple.

Anonymous classes aren't reusable.

Redirection to the object containing the listenedObject leads to gigantic classes that are hard to maintain.

Upvotes: 1

Roman
Roman

Reputation: 66196

Maybe it's not actually at the moment, but I believe that in the nearest future (after Java 7 release) something like this would be the common way:

listenedObject.addActionListener ( #{doSmth();} );

Upvotes: 0

Ha.
Ha.

Reputation: 3454

Beware that methods removeActionListener exists for a reason. You can skip listeners clean up if objects you listen to will die with object that handles events. But if your component listens the model supplied from external source, you should add your listeners in addNotify and remove them in removeNotify methods. Otherwise you may have a memore leak.

Upvotes: 0

oxbow_lakes
oxbow_lakes

Reputation: 134310

The way I have always found useful (for navigation purposes) is to create an anonymous inner class which then delegates to the outer class:

listenedObject.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent evt) {
        listenedObject_actionPerformed(evt);
    }
});


private void listenedObject_actionPerformed(ActionEvent evt) {
    //Your handling goes here
}

It is then much easier to get to your handling code in an IDE using a structural lookup (CTRL+F12 in IDEA, CTRL+O in Eclipse).

The problem of using a single class (like a GUI MyCoolPanel) as the common listener to a bunch of its components (buttons etc) is that the actionPerformed method then has a lot of ugly if-else comparisons to figure out which button has actually been pressed - not very OO at all!

You certainly should not get overly worried about the performance aspects of this kind of thing - they are likely to be negligible in the extreme! Premature optimization is famously a bad thing

Upvotes: 2

Riduidel
Riduidel

Reputation: 22300

Personnaly, when possible, i prefer to use an Action class (as an example a subclass of AbstractAction) instead of simply relying on an action listener. This way, I can provide the originating widget a name, an icon, a tooltip, and so on ...

Upvotes: 2

Daniel Bingham
Daniel Bingham

Reputation: 12914

The most common way to handle this - judging from my own personal experience - is to simply create an anonymous inline class. Like this:

listenedObject.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent evt) {
        // Your action handling code in here
    }
});

And often I've seen people place a call out to a method of the object containing the listenedObject. For example, in a Dialog that has a button:

myOkayButton.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent evt) {
        okayButtonPressed();
    }
});

Then later in the dialog class:

private void okayButtonPressed() {
    // Do what we need to do
}

Upvotes: 9

Related Questions