Events "occur" when the user manipulates the GUI of an applet or an
application. There are three kinds of objects that interact in event handling.
(1) an event generator, such as a Button or Menu.
(2) an event object which carries information about the event
(3) an event listener (handler) that is informed when the event occurs and which executes code to handle the event.
When an event (like a mousedown in a button) occurs, the event generator (button)
creates an event object (in this case an ActionEvent) and passes it as a parameter
to a function call made on each of its listeners. A generator can have several
listeners. In this case the method (function) is actionPerformed.
The event object has information in it about when the event occurred, where
the mouse was at the time, and the state of the keyboard at the time. It also
has a reference to the source (the generator of the event).
In the Java1.1 model, a generator can have several listeners, and each will
be informed when the generator generates an event. But the listeners must register
with the generator.
There are several different kinds of event objects (ActionEvent, MouseEvent...)
and several different kinds of listeners (ActionListener, MouseListener...).
If a component can generate a certain kind of event it will register listeners
of the appropriate kind. Buttons generate only ActionEvents and register only
ActionListeners. For example
Button stopButton = new Button("Stop"); // create a button
ActionListener stopListener = new StopListener(); // create a listener of a user defined type
stopButton.addActionListener(stopListener); // register the listener.
The programmer will also need to create the StopListener class, by implementing
the interface ActionListener and its single required method -- and maybe a constructor
if needed.
class StopListener implements ActionListener
{public void actionPerformed(ActionEvent e)
{ ... whatever should be done when the stop button is pushed.
}}
If the listener doesn't need to be used for anything except handling the event,
we can shorten the creation fragment to:
Button stopButton = new Button("Stop"); // create a button
stopButton.addActionListener(new StopListener()); // register a new listener.
Now, whenever that button is pushed, the actionPerformed method of each of its
registered listeners will be called and passed an appropriate ActionEvent object.
WARNING. Some of the books that you read will try to
short circuit this even more, by making the Applet class itself implement the
ActionListener interface. The rationale is that you need to write the Applet
class anyway and so all you need to do is let the Applet be a listener for all
events that its parts generate. Thus if the applet contains a button, you might
see:
class MyApplet extends Applet implements ActionListener // WARNING POOR PRACTICE
{ .... other Applet code, like paint...public void actionPerformed(ActionEvent e)
{ ... whatever should be done when the stop button is pushed.
}
public void init() // the Applet's required init method
{...
Button stopButton = new Button("Stop"); // create a button
stopButton.addActionListener(this); // register the Applet itself as listener.}
}
This is a TERRIBLE way to build code. First it gives the Applet too much to
do and is therefore not a good OOP design. Secondly, if you have more than one
generator of ActionEvents, then the single actionPerformed is going to have
to switch on the source to determine which object generated the event so it
knows what to do. This testing will only slow your program down and make it
harder to maintain. You will read code like this, BUT DO NOT
WRITE IT.
Each event generator should have its own specially created listeners. You should
share listeners (one listener for two or more generators) when the logic of
the program requires exactly the same action to be taken when the generators
are manipulated. This is often the case with a Button and a TextField. They
both generate ActionEvents, the button when it is pressed and the Field when
the enter key is pressed while the user is typing into it. You sometimes want
the button to send the string entered into the text field to some other place
in the program (or over the net). By giving the TextField the same action listener
as the button, then the same thing will occur if the user simply types and then
hits enter, rather than pressing the button.
Events are discussed at length in the Nutshell book, starting on page 150. There
are many examples in my GUI tutorial. Also see the paper on Java
Event Patterns.