CHAPTER-14
Event Delegation Model
What is an Event?
Change in the state of an object is known as event i.e. event describes the change in state of
source. Events are generated as result of user interaction with the graphical user interface
components. For example, clicking on a button, moving the mouse, entering a character through
keyboard, selecting an item from list, scrolling the page are the activities that causes an event to
happen.
Types of Event
The events can be broadly classified into two categories:
• Foreground Events - Those events which require the direct interaction of user.They are
generated as consequences of a person interacting with the graphical components in
Graphical User Interface. For example, clicking on a button, moving the mouse, entering a
character through keyboard,selecting an item from list, scrolling the page etc.
• Background Events - Those events that don’t require the interaction of end user are known
as background events. Operating system interrupts, hardware or software failure, timer
expires, an operation completion are the example of background events.
In AWT components, we came to know every component (except Panel and Label) generates
events when interacted by the user like clicking over a button or pressing enter key in a text field
etc. Listeners handle the events. Let us know the style (or design pattern) Java follows to handle
the events.
AWT Event-Handling
Java adopts the so-called "Event-Driven" (or "Event-Delegation") programming model for event-
handling, similar to most of the visual programming languages (such as Visual Basic and
Dot.NET etc).
The AWT's event-handling classes are kept in package java.awt.event.
The source object (such as Button and Textfield) interacts with the user. Upon triggered, it
creates an event object. This event object will be messaged to all the registered listener object(s),
and an appropriate event-handler method of the listener(s) is called-back to provide the response.
In other words, triggering a source fires an event to all its listener(s), and invoke an appropriate
handler of the listener(s).
Three objects are involved in the event-handling: a source, listener(s) and an event object.
The sequence of steps is illustrated above:
1. The source object registers its listener(s) for a certain type of event.
Source object fires event upon triggered. For example, clicking an Button fires an ActionEvent,
mouse-click fires MouseEvent, key-type fires KeyEvent, etc.
How the source and listener understand each other? The answer is via an agreed-upon interface.
For example, if a source is capable of firing an event called XxxEvent (e.g., MouseEvent)
involving various operational modes (e.g., mouse-clicked, mouse-entered, mouse-exited, mouse-
pressed, and mouse-released). Firstly, we need to declare an interface called XxxListener (e.g.,
MouseListener) containing the names of the handler methods. Recall that an interface contains
only abstract methods without implementation. For example,
// A MouseListener interface, which declares the signature of the handlers
// for the various operational modes.
public interface MouseListener
{
public void mousePressed(MouseEvent evt);//Called back upon mouse-button pressed
public void mouseReleased(MouseEvent evt); // Called back upon mouse-button released
public void mouseClicked(MouseEvent evt); // Called back upon mouse-button clicked (pressed
and released)
public void mouseEntered(MouseEvent evt); // Called back when mouse pointer entered the
component
public void mouseExited(MouseEvent evt); // Called back when mouse pointer exited the
component
Event Delegation Model
Event Handling is the mechanism that controls the event and decides what should happen if an
event occurs. This mechanism have the code which is known as event handler that is executed
when an event occurs. Java uses the Delegation Event Model to handle the events. This model
defines the standard mechanism to generate and handle the events. Let's have a brief introduction
to this model.
Flow of Event Delegation:
[User Action] → [Event Source] → [Generates Event Object] → [Delegates to Listener]
The listener is registered with the source using methods like addActionListener().
+-----------------+ event Object +--------------------------+
| Source |---------------------------> | Listener |
| (e.g., JButton) | calls method | (e.g., ActionListener) |
+-----------------+ <-------------------------> | registered to it |
registerListener()
The Event Delegation Model is based on three key components:
Component Description
Event Source The GUI component (e.g., JButton) that generates the event.
Event Object The object (e.g., ActionEvent) that contains information about the event.
Event Listener The interface (e.g., ActionListener) that defines methods to handle the event.
The Delegation Event Model has the following key Components:
1. Event Sources Source
2. Event Object classes
3. Event Listeners
4. Event Adapters Listener
The source is an object on which event occurs. Source is responsible for providing information
of the occurred event to it's handler. Java provide as with classes for source object.
I Event Sources
Event sources are components, subclasses of java.awt.Component, capable to generate events.
The event source can be a button, TextField or a Frame etc.
II Event Object classes
Almost every event source(except Panel and Label) generates an event and is named by some
Java class. For example, the event generated by button is known as ActionEvent and that of
Checkbox is known as ItemEvent. All the events are listed in java.awt.event package.
Following list gives a few components and their corresponding listeners.
Component Event it generates
Button, TextField, ActionEvent
List, Menu
Frame WindowEvent
Checkbox, Choice, ItemEvent
List
Scrollbar AdjustmentEvent
Mouse (hardware) MouseEvent
Keyboard KeyEvent
(hardware)
The events generated by hardware components (like MouseEvent and KeyEvent) are known as
low-level events and the events generated by software components (like Button, List) are known
as semantic events.
Event Listeners
The events generated by the GUI components are handled by a special group of interfaces known
as "listeners". Note, Listener is an interface. Every component has its own listener, say,
AdjustmentListener handles the events of scrollbar. Some listeners handle the events of
multiple components. For example, ActionListener handles the events of Button, TextField, List
and Menus. Listeners are from java.awt.event package.
4. Event Adapters
When a listener includes many abstract methods to override, the coding becomes heavy to the
programmer. For example, to close the frame, you override seven abstract methods of
WindowListener, in which, infact you are using only one method. To avoid this heavy coding,
the designers come with another group of classes known as "adapters". Adapters are abstract
classes defined in java.awt.event package. Every listener that has more than one abstract method
has got a corresponding adapter class.
Adapters are abstract classes for receiving various events. The methods in these classes are
empty. These classes exists as convenience for creating listener objects.
Following is the list of commonly used adapters while listening GUI events in AWT.
Sr. No. Adapter & Description
FocusAdapter
1
An abstract adapter class for receiving focus events.
KeyAdapter
2
An abstract adapter class for receiving key events.
MouseAdapter
3
An abstract adapter class for receiving mouse events.
MouseMotionAdapter
4
An abstract adapter class for receiving mouse motion events.
WindowAdapter
5
An abstract adapter class for receiving window events.
Steps involved in event handling
• The User clicks the button and the event is generated.
• Now the object of concerned event class is created automatically and information about the
source and the event get populated with in same object.
• Event object is forwarded to the method of registered listener class.
• the method is now get executed and returns.
Points to remember about listener
• In order to design a listener class we have to develop some listener interfaces. These Listener
interfaces forecast some public abstract callback methods which must be implemented by
the listener class.
• If you do not implement the any if the predefined interfaces then your class can not act as a
listener class for a source object.
What happens internally at a button click?
We know the events are handled by listeners and ActionListener handles the events of a button.
Observe the following skeleton code.
Event Handling by Implementing actionPerform() of ActionerListener
Interaface
public class ButtonDemo extends Frame implements ActionListener
{
public ButtonDemo()
{
Button btn = new Button("OK");
btn.addActionListener(this);
add(btn);
}
public void actionPerformed(ActionEvent e)
{
String str = e.getActionCommand();
}
}
3. Now, the question is, what ActionListener does with the ActionEvent object it received?
The ActionListener simply calls actionPerformed() method and passes the ActionEvent object
to the parameter as follows.
public void actionPerformed(ActionEvent e)
The parameter for the above method comes from ActionListener.
4. Finally the ActionEvent object generated by the button btn reaches the e object of
ActionEvent. All this is done by JVM implicitly. For this reason, the getActionCommand()
method of ActionEvent class knows the label of the button btn.
String str = e.getActionCommand();
The e represents an object of ActionEvent and the value for the e is coming from button btn. str
is nothing but the label of the button OK.
Event Handling with Inner classes
A nested class (or commonly called inner class) is a class defined inside another class -
introduced in JDK 1.1. As an illustration, two nested classes MyNestedClass1 and
MyNestedClass2 are defined inside the definition of an outer class called MyOuterClass.
public class MyOuterClass { // outer class defined here
......
private class MyNestedClass1 { ...... } // an nested class defined inside
the outer class
public static class MyNestedClass2 { ...... } // an "static" nested class
defined inside the outer class
......
}
A nested class has these properties:
1. A nested class is a proper class. That is, it could contain constructors, member variables
and member methods. You can create an instance of a nested class via the new operator
and constructor.
2. A nested class is a member of the outer class, just like any member variables and methods
defined inside a class.
3. Most importantly, a nested class can access the private members (variables/methods) of
the enclosing outer class, as it is at the same level as these private members. This is the
property that makes inner class useful.
4. A nested class can have private, public, protected, or the default access, just like any
member variables and methods defined inside a class. A private inner class is only
accessible by the enclosing outer class, and is not accessible by any other classes. [An
top-level outer class cannot be declared private, as no one can use a private outer
class.]
5. A nested class can also be declared static, final or abstract, just like any ordinary
class.
6. A nested class is NOT a subclass of the outer class. That is, the nested class does not
inherit the variables and methods of the outer class. It is an ordinary self-contained class.
[Nonetheless, you could declare it as a subclass of the outer class, via keyword "extends
OuterClassName", in the nested class's definition.]
The usages of nested class are:
1. To control visibilities (of the member variables and methods) between inner/outer class.
The nested class, being defined inside an outer class, can access private members of the
outer class.
2. To place a piece of class definition codes closer to where it is going to be used, to make
the program clearer and easier to understand.
3. For namespace management.
Example of Inner Class as Event Listener
A nested class is useful if you need a small class which relies on the enclosing outer class for its
private variables and methods. It is ideal in an event-driven environment for implementing event
handlers. This is because the event handling methods (in a listener) often require access to the
private variables (e.g., a private TextField) of the outer class.
In this example (revisit Example 1 AWTCounter), we define an inner class called
BtnCountListener, and create an instance of BtnCountListener as the ActionEvent listener
for the btnCount. The BtnCountListener needs to implement the ActionListener interface,
and override the actionPerformed() handler. BtnCountListener needs to be defined as an
inner class, as it needs to access private variables (count and tfCount) of the outer class.
import java.awt.*;
import java.awt.event.*;
// An AWT GUI program inherits from the top-level container java.awt.Frame
public class AWTCounter extends Frame {
// The event-handler actionPerformed() needs to access these "private" variables
private TextField tfCount;
private Button btnCount;
private int count = 0;
// Constructor to setup the GUI components and event handlers
public AWTCounter() {
setLayout(new FlowLayout()); // "super" Frame sets to FlowLayout
add(new Label("Counter")); // An anonymous instance of Label
tfCount = new TextField("0", 10);
tfCount.setEditable(false); // read-only
add(tfCount); // "super" Frame adds tfCount
btnCount = new Button("Count");
add(btnCount); // "super" Frame adds btnCount
// Construct an anonymous instance of BtnCountListener (a named inner class).
// btnCount adds this instance as a ActionListener.
btnCount.addActionListener(new BtnCountListener());
setTitle("AWT Counter");
setSize(250, 100);
setVisible(true);
}
// The entry main method
public static void main(String[] args) {
new AWTCounter(); // Let the constructor do the job
}
/**
* BtnCountListener is a "named inner class" used as ActionListener.
* This inner class can access private variables of the outer class.
*/
private class BtnCountListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent evt) {
++count;
tfCount.setText(count + "");
}
}
}
An Anonymous Inner Class as Event Listener
Instead of using a named inner class (called BtnCountListner in the previous example), we
shall use an inner class without a name, known as anonymous inner class as the
ActionListener in this example.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class SwingCounterAnonymousInnerClass extends JFrame {
private JTextField tfCount;
private JButton btnCount;
private int count = 0;
public SwingCounterAnonymousInnerClass() {
setLayout(new FlowLayout());
add(new JLabel("Counter")); // Swing JLabel
tfCount = new JTextField("0", 10);
tfCount.setEditable(false);
add(tfCount); // JTextField
btnCount = new JButton("Count");
add(btnCount); // JButton
// Add ActionListener using anonymous inner class
btnCount.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
++count;
tfCount.setText(String.valueOf(count));
}
});
setTitle("Swing Counter");
setSize(250, 100);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null); // Center the frame
setVisible(true);
}
public static void main(String[] args) {
new SwingCounterAnonymousInnerClass());
}
}
Dissecting the Program
• The anonymous inner class is given a name generated by the compiler, and compiled into
OuterClassName$n.class, where n is a running number of the inner classes of this
outer class.
• An anonymous instance of an anonymous inner class is constructed, and passed as the
argument of the addActionListener() method as follows:
btnCount.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent evt) {
++count;
tfCount.setText(count + "");
}
});
The above codes is equivalent to and compiled as:
private class N implements ActionListener
{ // N is a running number of the inner classes created
@Override
public void actionPerformed(ActionEvent evt) {
++count;
tfCount.setText(count + "");
}
}
btnCount.addActionListener(new N());
// Or
N n = new N()
btnCount.addActionListener(n);
• From JDK 8, you can write the event handler using "Lambda Expression" in a one-liner
as follows:
btnCount.addActionListener(evt -> tfCount.setText(++count + ""));
you can convert your ActionListener implementation into a lambda expression if you're
assigning the listener directly to buttons. Here's how to do it with lambda syntax,
assuming you're using Java 8 or higher:
Properties of Anonymous Inner Class
1. The anonymous inner class is define inside a method, instead of a member of the outer
class (class member). It is local to the method and cannot be marked with access modifier
(such as public, private) or static, just like any local variable of a method.
2. An anonymous inner class must always extend a superclass or implement an interface.
The keyword "extends" or "implements" is NOT required in its declaration. An
anonymous inner class must implement all the abstract methods in the superclass or in the
interface.
3. An anonymous inner class always uses the default (no-arg) constructor from its
superclass to create an instance. If an anonymous inner class implements an interface, it
uses the java.lang.Object().
4. An anonymous inner class is compiled into a class named OuterClassName$n.class,
where n is a running number of inner classes within the outer class.
5. An instance of an anonymous inner class is constructed via this syntax:
6. new SuperClassName/InterfaceName() { // extends superclass or
implements interface
7. // invoke the default no-arg
constructor or Object[]
8. // Implement abstract methods in superclass/interface
9. // More methods if necessary
10. ......
}
Using the Same Listener Instance for All the Buttons
If you use the same instance as the listener for all the 3 buttons, you need to determine which
button has fired the event. It is because all the 3 buttons trigger the same event-handler method.
Using ActionEvent's getActionCommand()
In the following example, we use the same instance of a "named" inner class as the listener for
all the 3 buttons. The listener needs to determine which button has fired the event. This can be
accomplished via the ActionEvent's getActionCommonad() method, which returns the button's
label.
import java.awt.*;
import java.awt.event.*;
// An AWT GUI program inherits the top-level container java.awt.Frame
public class AWTCounter3Buttons1Listener extends Frame {
private TextField tfCount;
private Button btnCountUp, btnCountDown, btnReset;
private int count = 0;
// Constructor to setup the GUI components and event handlers
public AWTCounter3Buttons1Listener () {
setLayout(new FlowLayout());
add(new Label("Counter"));
tfCount = new TextField("0", 10);
tfCount.setEditable(false);
add(tfCount);
// Construct Buttons
btnCountUp = new Button("Count Up");
add(btnCountUp);
btnCountDown = new Button("Count Down");
add(btnCountDown);
btnReset = new Button("Reset");
add(btnReset);
// Allocate an instance of the "named" inner class BtnListener.
AllButtonsListener listener = new AllButtonsListener();
// Use the same listener instance for all the 3 Buttons.
btnCountUp.addActionListener(listener);
btnCountDown.addActionListener(listener);
btnReset.addActionListener(listener);
setTitle("AWT Counter");
setSize(400, 100);
setVisible(true);
}
// The entry main method
public static void main(String[] args) {
new AWTCounter3Buttons1Listener(); // Let the constructor do the job
}
/**
* AllButtonsListener is an named inner class used as ActionEvent listener
for all the Buttons.
*/
private class AllButtonsListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent evt) {
// Need to determine which button fired the event.
// the getActionCommand() returns the Button's label
String btnLabel = evt.getActionCommand();
if (btnLabel.equals("Count Up")) {
++count;
} else if (btnLabel.equals("Count Down")) {
--count;
} else {
count = 0;
}
tfCount.setText(count + "");
}
}
}
Using getSource() of EventObject
Besides the getActionCommand(), which is only available for ActionEvent, you can use the
getSource() method, which is available to all event objects, to retrieve a reference to the source
object that has fired the event. getSource() returns a java.lang.Object. You may need to
downcast it to the proper type of the source object. For example,
1 import java.awt.*;
2 import java.awt.event.*;
3
4 public class AWTCounter3ButtonsGetSource extends Frame {
5 private TextField tfCount;
6 private Button btnCountUp, btnCountDown, btnReset;
7 private int count = 0;
8
9 // Constructor to setup the GUI components and event handlers
10 public AWTCounter3ButtonsGetSource () {
11 setLayout(new FlowLayout());
12 add(new Label("Counter"));
13 tfCount = new TextField("0", 10);
14 tfCount.setEditable(false);
15 add(tfCount);
16
17 // Construct Buttons
18 btnCountUp = new Button("Count Up");
19 add(btnCountUp);
20 btnCountDown = new Button("Count Down");
21 add(btnCountDown);
22 btnReset = new Button("Reset");
23 add(btnReset);
24
25 // Allocate an instance of inner class BtnListener.
26 AllButtonsListener listener = new AllButtonsListener();
27 // Use the same listener instance to all the 3 Buttons.
28 btnCountUp.addActionListener(listener);
29 btnCountDown.addActionListener(listener);
30 btnReset.addActionListener(listener);
31
32 setTitle("AWT Counter");
33 setSize(400, 100);
34 setVisible(true);
35 }
36
37 // The entry main method
38 public static void main(String[] args) {
39 new AWTCounter3ButtonsGetSource(); // Let the constructor do the job
40 }
41
42 /**
43 * AllButtonsListener is a named inner class used as ActionEvent
44 listener for all the Buttons.
45 */
46 private class AllButtonsListener implements ActionListener {
47 @Override
48 public void actionPerformed(ActionEvent evt) {
49 // Need to determine which button has fired the event.
50 Button source = (Button)evt.getSource();
51 // Get a reference of the source that has fired the event.
52 // getSource() returns a java.lang.Object. Downcast back to
53 Button.
54 if (source == btnCountUp) {
55 ++count;
56 } else if (source == btnCountDown) {
57 --count;
58 } else {
59 count = 0;
60 }
61 tfCount.setText(count + "");
62 }
}
}
Adapter Classes?
Adapter classes in Java are predefined abstract classes that provide empty implementations of
listener interfaces. They are part of the java.awt.event package and are used in event handling in
AWT and Swing applications.
They are useful when:
• You want to handle only a few methods of a listener interface.
• But the interface contains multiple abstract methods.
Instead of implementing all methods (even the unused ones), adapter classes let you override
only the required methods.
Why Use Adapter Classes?
Many Swing/AWT listener interfaces contain multiple methods. If you only need one or two,
adapter classes help avoid boilerplate code.
Example: MouseListener has 5 methods. You may only want mouseClicked(). Adapter classes
let you do just that.
Commonly Used Adapter Classes
Listener Interface Adapter Class
MouseListener MouseAdapter
KeyListener KeyAdapter
WindowListener WindowAdapter
FocusListener FocusAdapter
ComponentListener ComponentAdapter
All are found in: java.awt.event.*
Syntax: Using an Adapter Class
addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
// Handle mouse click
}
});
You only override the method(s) you care about.
Example: MouseAdapter
import javax.swing.*;
import java.awt.event.*;
public class MouseAdapterExample {
public static void main(String[] args) {
JFrame frame = new JFrame("MouseAdapter Example");
JLabel label = new JLabel("Click anywhere inside the frame");
label.setHorizontalAlignment(SwingConstants.CENTER);
frame.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
label.setText("Mouse Clicked at X=" + e.getX() + ", Y=" + e.getY());
}
});
frame.add(label);
frame.setSize(300, 200);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
Benefits of Using Adapter Classes
• Cleaner code (override only needed methods)
• Reduces boilerplate
• Simplifies anonymous class usage
Conclusion
Adapter classes are a convenient tool for handling GUI events when you don't want to implement
all the methods of a listener interface. They're essential for building clean, efficient event-driven
programs in Java Swing or AWT.
Another Example of MouseEvent and MouseListener Interface
A MouseEvent is fired to all its registered listeners, when you press, release, or click (press
followed by release) a mouse-button (left or right button) at the source object; or position the
mouse-pointer at (enter) and away (exit) from the source object.
A MouseEvent listener must implement the MouseListener interface, which declares the
following five abstract methods:
public void mouseClicked(MouseEvent e)
// Called-back when the mouse-button has been clicked (pressed followed by released) on the
source.
public void mousePressed(MouseEvent e)
public void mouseReleased(MouseEvent e)
// Called-back when a mouse-button has been pressed/released on the source.
// A mouse-click invokes mousePressed(), mouseReleased() and mouseClicked().
public void mouseEntered(MouseEvent e)
public void mouseExited(MouseEvent e)
// Called-back when the mouse-pointer has entered/exited the source.
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
public class MouseEventDemo extends Frame implements MouseListener {
// Private variables
private TextField tfMouseX; // to display mouse-click-x
private TextField tfMouseY; // to display mouse-click-y
// Constructor - Setup the UI
public MouseEventDemo() {
setLayout(new FlowLayout()); // "super" frame sets layout
// Label
add(new Label("X-Click: ")); // "super" frame adds component
// TextField
tfMouseX = new TextField(10); // 10 columns
tfMouseX.setEditable(false); // read-only
add(tfMouseX); // "super" frame adds component
// Label
add(new Label("Y-Click: ")); // "super" frame adds component
// TextField
tfMouseY = new TextField(10);
tfMouseY.setEditable(false); // read-only
add(tfMouseY); // "super" frame adds component
addMouseListener(this);
// "super" frame fires the MouseEvent
// "super" frame adds "this" object as MouseEvent listener
setTitle("MouseEvent Demo"); // "super" Frame sets title
setSize(350, 100); // "super" Frame sets initial size
setVisible(true); // "super" Frame shows
}
public static void main(String[] args) {
new MouseEventDemo(); // Let the constructor do the job
}
// MouseEvent handlers
@Override
public void mouseClicked(MouseEvent e) {
tfMouseX.setText(e.getX() + "");
tfMouseY.setText(e.getY() + "");
}
@Override
public void mousePressed(MouseEvent e) { }
@Override
public void mouseReleased(MouseEvent e) { }
@Override
public void mouseEntered(MouseEvent e) { }
@Override
public void mouseExited(MouseEvent e) { }
}
In this example, we setup a GUI with 4 components (two Labels and two non-editable
TextFields), inside a top-level container Frame, arranged in FlowLayout.
To demonstrate the MouseEvent:
1. We identity super Frame as the
2. The Frame fires a MouseEvent to all its MouseEvent listener(s) when you
click/press/release a mouse-button or enter/exit with the mouse-pointer.
3. We select this object as the MouseEvent listener (for simplicity).
4. We register this object as the MouseEvent listener to super Frame (source) via the
method addMouseListener(this).
5. The listener (this class) is required to implement the MouseListener interface, which
declares 5 abstract methods: mouseClicked(), mousePressed(), mouseReleased(),
mouseEntered(), and mouseExit(). We override the mouseClicked() to display the (x, y)
co-ordinates of the mouse click on the two displayed TextFields. We ignore all the other
handlers (for simplicity - but you need to provide an empty body for compilation).
Try: Include a WindowListener to handle the close-window button.
Example 5: MouseEvent and MouseMotionListener Interface
A MouseEvent is also fired when you moved and dragged the mouse pointer at the source object.
But you need to use MouseMotionListener to handle the mouse-move and mouse-drag. The
MouseMotionListener interface declares the following two abstract methods:
public void mouseDragged(MouseEvent e)
// Called-back when a mouse-button is pressed on the source component and then dragged.
public void mouseMoved(MouseEvent e)
// Called-back when the mouse-pointer has been moved onto the source component but no
buttons have been pushed.