The Ultimate Guide to Event-driven Programming in Java

Did You Know That Event-driven Programming Is One of the Most Popular and Widely Used Programming Paradigms in the World?

Eidan Khan
JavaJams
8 min readJan 31, 2024

--

Have you ever wondered how applications can respond to user input, network activity, timer expiration, and other changes in their state or environment? The answer is event-driven programming, a paradigm that allows developers to create applications that react to events.

Event-driven programming is one of the most popular and widely used programming paradigms in the world, with 69.4% of developers using it in some form or another. It enables applications to be more interactive, responsive, and scalable, as well as easier to maintain and test.

Image Generated By DALL-E 3

In this article, you will learn the basics of event-driven programming in Java. You will learn how to:

  • Define and generate events
  • Create and register event listeners
  • Handle different types of events

By the end of this article, you will have a solid understanding of event-driven programming in Java and how to apply it to your own projects.

You can also find the complete source code of this article on my below GitHub repository:

https://github.com/eidankhan/eventdriven-programming.git

How to Define and Generate Events?

An event is an object that represents a change in the state of an application or its environment. For example, when a user clicks a button, an event object is created that contains information about the click, such as the source, the location, the time, etc. Events can also be generated by other sources, such as the operating system, the network, the database, etc.

In Java, events are represented by classes that extend the java.util.EventObject class. This class provides two methods: getSource() and toString(). The getSource() method returns the object that generated the event, and the toString() method returns a string representation of the event.

To create a custom event class, you need to extend the EventObject class and provide a constructor that accepts the source object as a parameter. You can also add additional fields and methods to store and access more information about the event. For example, here is a simple event class that represents a temperature change:

import java.util.EventObject;

public class TemperatureChangeEvent extends EventObject {

private double oldTemperature;
private double newTemperature;

public TemperatureChangeEvent(Object source, double oldTemperature, double newTemperature) {
super(source);
this.oldTemperature = oldTemperature;
this.newTemperature = newTemperature;
}

public double getOldTemperature() {
return oldTemperature;
}

public double getNewTemperature() {
return newTemperature;
}
}

To generate an event, you need to create an instance of the event class and pass it to the listeners. You can use a list or a set to store the references to the listeners, and iterate over them to notify them of the event. For example, here is a simple class that represents a thermometer and generates temperature change events:

import java.util.ArrayList;
import java.util.List;

public class Thermometer {

private double temperature;
private List<TemperatureChangeListener> listeners;

public Thermometer(double temperature) {
this.temperature = temperature;
this.listeners = new ArrayList<>();
}

public double getTemperature() {
return temperature;
}

public void setTemperature(double temperature) {
double oldTemperature = this.temperature;
this.temperature = temperature;
TemperatureChangeEvent event = new TemperatureChangeEvent(this, oldTemperature, temperature);
fireTemperatureChangeEvent(event);
}

public void addTemperatureChangeListener(TemperatureChangeListener listener) {
listeners.add(listener);
}

public void removeTemperatureChangeListener(TemperatureChangeListener listener) {
listeners.remove(listener);
}

private void fireTemperatureChangeEvent(TemperatureChangeEvent event) {
for (TemperatureChangeListener listener : listeners) {
listener.temperatureChanged(event);
}
}
}

In this section, we have learned how to define and generate events in Java. We have seen how to create a custom event class by extending the EventObject class, and how to generate an event by creating an instance of the event class and passing it to the listeners. We have also seen an example of a custom event class and a class that generates events. In the next section, we will learn how to create and register event listeners in Java.

How to Create and Register Event Listeners?

An event listener is an object that can receive and process a specific type of event. For example, when a temperature change event occurs, an event listener can print the temperature change or perform some calculation.

In Java, event listeners are represented by interfaces that define one or more methods to handle a specific type of event. To create a custom event listener interface, you need to extend the java.util.EventListener interface and declare the methods that accept the event object as a parameter. For example, here is a simple event listener interface that handles temperature change events:

import java.util.EventListener;

public interface TemperatureChangeListener extends EventListener {

void temperatureChanged(TemperatureChangeEvent event);
}

To create an event listener, you need to implement the event listener interface and provide the implementation for the methods. You can also register the listener with the event source using the appropriate method. For example, here is a simple event listener that prints the temperature change:

public class TemperaturePrinter implements TemperatureChangeListener {

@Override
public void temperatureChanged(TemperatureChangeEvent event) {
System.out.println("Temperature changed from " + event.getOldTemperature() + " to " + event.getNewTemperature());
}
}

To register this listener with a thermometer, you would use the addTemperatureChangeListener method:

Thermometer thermometer = new Thermometer(25.0);
TemperaturePrinter printer = new TemperaturePrinter();
thermometer.addTemperatureChangeListener(printer);

Now, whenever the temperature of the thermometer changes, the printer will print the change.

In this section, we have learned how to create and register event listeners in Java. We have seen how to create a custom event listener interface by extending the EventListener interface, and how to create an event listener by implementing the event listener interface and providing the implementation for the methods. We have also seen how to register the listener with the event source using the appropriate method. We have also seen an example of a custom event listener interface and a class that implements it and registers it with the event source. In the next section, we will learn how to handle different types of events in Java.

How to Handle Different Types of Events?

Java provides a number of built-in event classes and event listener interfaces for common types of events, such as user interface events, mouse events, keyboard events, window events, etc. These classes and interfaces are defined in the java.awt.event and javax.swing.event packages. You can use these classes and interfaces to handle events from various components, such as buttons, text fields, menus, frames, etc.

To handle these events, you need to follow the same steps as for custom events: implement the event listener interface, provide the implementation for the methods, and register the listener with the event source. However, you do not need to create your own event classes or event listener interfaces, as they are already provided by the Java API.

The different types of events that Java provides are categorized into two groups: low-level events and semantic events. Low-level events are events that are generated by the physical devices, such as the mouse, the keyboard, the window system, etc. Semantic events are events that are generated by the logical actions of the user, such as clicking a button, selecting an item, closing a window, etc.

The following table shows some of the most common types of events and their corresponding event classes and event listener interfaces:

+----------------+-----------------------------+-----------------------------+------------------------------------------------------------------+
| Event Type | Event Class | Event Listener Interface | Description |
+----------------+-----------------------------+-----------------------------+------------------------------------------------------------------+
| Action Event | java.awt.event.ActionEvent | java.awt.event.ActionListener| An event that indicates that a component-defined action occurred, |
| | | | such as clicking a button, choosing a menu item, etc. |
+----------------+-----------------------------+-----------------------------+------------------------------------------------------------------+
| Item Event | java.awt.event.ItemEvent | java.awt.event.ItemListener | An event that indicates that an item was selected or deselected, |
| | | | such as a checkbox, a radio button, a list, etc. |
+----------------+-----------------------------+-----------------------------+------------------------------------------------------------------+
| Mouse Event | java.awt.event.MouseEvent | java.awt.event.MouseListener| An event that indicates that a mouse action occurred, such as |
| | | | pressing, releasing, clicking, entering, or exiting a component. |
+----------------+-----------------------------+-----------------------------+------------------------------------------------------------------+
| Mouse Motion | java.awt.event.MouseEvent | java.awt.event.MouseMotion | An event that indicates that a mouse motion occurred, such as |
| Event | | Listener | moving or dragging the mouse over a component. |
+----------------+-----------------------------+-----------------------------+------------------------------------------------------------------+
| Key Event | java.awt.event.KeyEvent | java.awt.event.KeyListener | An event that indicates that a key action occurred, such as |
| | | | pressing, releasing, or typing a key on the keyboard. |
+----------------+-----------------------------+-----------------------------+------------------------------------------------------------------+
| Window Event | java.awt.event.WindowEvent | java.awt.event.WindowListener| An event that indicates that a change in the state of a window |
| | | | occurred, such as opening, closing, iconifying, deiconifying, |
| | | | activating, or deactivating a window. |
+----------------+-----------------------------+-----------------------------+------------------------------------------------------------------+

To handle these events, you need to implement the corresponding event listener interface and provide the implementation for the methods that accept the event object as a parameter. For example, to handle action events from a button, you would implement the ActionListener interface and provide the implementation for the actionPerformed method:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;

public class ButtonHandler implements ActionListener {

@Override
public void actionPerformed(ActionEvent e) {
System.out.println("Button clicked!");
}
}

You also need to register the listener with the event source using the appropriate method. For example, to register the listener with a button, you would use the addActionListener method:

JButton button = new JButton("Click me!");
ButtonHandler handler = new ButtonHandler();
button.addActionListener(handler);

Now, whenever the button is clicked, the listener will print a message.

“You can also use anonymous inner classes or lambda expressions to create and register event listeners in a more concise way. Anonymous inner classes are classes that have no name and are defined within another class. Lambda expressions are expressions that represent a single method without a name. Both anonymous inner classes and lambda expressions can be used to implement functional interfaces, which are interfaces that have only one abstract method.”

For example, the above code can be rewritten using an anonymous inner class as:

JButton button = new JButton("Click me!");
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("Button clicked!");
}
});

Or using a lambda expression as:

JButton button = new JButton("Click me!");
button.addActionListener(e -> System.out.println("Button clicked!"));

Both anonymous inner classes and lambda expressions can make your code more compact and readable, but they also have some limitations and drawbacks. You should use them with caution and only when they make sense.

In this section, we have learned how to handle different types of events in Java. We have seen how to use the built-in event classes and event listener interfaces from the Java API to handle events from various components. We have also seen how to use anonymous inner classes and lambda expressions to create and register event listeners in a concise way. We have also seen an example of handling a built-in event from a GUI component using the predefined event class and event listener interface. In the next section, we will learn how to use various frameworks and libraries for event-driven programming in Java.

In this article, we have learned the basics of event-driven programming in Java. We have learned how to:

  • Define and generate events
  • Create and register event listeners
  • Handle different types of events

Event-driven programming is a powerful paradigm that allows developers to create applications that respond to events. Events are changes in the state of an application or its environment, such as user input, network activity, timer expiration, etc. Event-driven programming enables applications to be more interactive, responsive, and scalable.

We hope you enjoyed this article and learned something new. If you have any questions or feedback, feel free to leave a comment below. Happy coding! 😊

--

--

Eidan Khan
JavaJams

🚀 Full-stack Dev | Tech Content Creator 📝 For more in-depth articles, tutorials, and insights, visit my blog at JavaJams.org.