CodeGym /Courses /JAVA 25 SELF /Events in Swing and AWT: basics, examples

Events in Swing and AWT: basics, examples

JAVA 25 SELF
Level 50, Lesson 1
Available

1. A very brief introduction to Swing and AWT

If Java were a car, then Swing and AWT are its “dashboard” and “steering wheel.” AWT (Abstract Window Toolkit) is the very first library for building desktop applications in Java. It uses the OS’s native controls, so it looks different on Windows, Linux, and Mac.

Swing is a more modern layer on top of AWT, written entirely in Java. Swing is prettier, more flexible, supports lots of additional features, and looks the same on all platforms (well, almost). In both cases, all UI components (buttons, text fields, check boxes, etc.) support events.

In this lecture we will use Swing: it is simpler for beginners and appears more often in learning examples. Let’s figure out how event handling works using the most popular task—reacting to a button click.

Creating a button

In Swing, a button is created like this:

JButton button = new JButton("Click me!");

Here, “Click me!” is the label on the button.

Adding a listener

To react to the click, you need to “subscribe” a listener to the event:

button.addActionListener(new MyActionListener());

But what is this MyActionListener? It is a class that implements the ActionListener interface:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class MyActionListener implements ActionListener {
    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println("The button was clicked!");
    }
}

When the user clicks the button, Swing calls the actionPerformed method on all listeners registered via addActionListener.

Full example: a simple window with a button

Let’s put it all together and create a working application:

import javax.swing.*;
import java.awt.event.*;

public class SimpleButtonApp {
    public static void main(String[] args) {
        JFrame frame = new JFrame("Event example");
        JButton button = new JButton("Click me!");

        // Add a listener to the button
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("The button was clicked!");
                JOptionPane.showMessageDialog(frame, "Hooray! The button was clicked!");
            }
        });

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(button);
        frame.setSize(300, 200);
        frame.setVisible(true);
    }
}

What happens here:

  • Create a window (JFrame).
  • Create a button (JButton).
  • Add a listener (an anonymous class so we don’t create separate files).
  • Inside actionPerformed, we print a message to the console and show a pop-up dialog (JOptionPane).
  • Add the button to the window and show the window to the user.

Try it yourself: copy this code, run it—and click the button!

2. Anonymous classes and lambda expressions

In modern Java code, writing separate classes for a single handler is like taking a tank to buy bread. It’s much more convenient to use anonymous classes or lambda expressions.

Anonymous class

We already saw this approach above:

button.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        // handling code
    }
});

Here, the class is declared right in place, without a name.

Lambda expression (Java 8+)

If the listener interface is functional (that is, it contains only one abstract method), you can use a lambda:

button.addActionListener(e -> {
    System.out.println("Button clicked via lambda!");
});

Or even shorter if the body is one line:

button.addActionListener(e -> System.out.println("Lambda: button clicked!"));

This not only shortens the code but also makes it more readable. Fun fact: the ActionListener interface is functional because it has only one method, actionPerformed.

4. Other kinds of events

The world isn’t limited to buttons! In Swing and AWT, almost every UI component supports its own events. Here are the most popular ones:

Mouse events: MouseListener and MouseAdapter

If you want to react to mouse clicks, use MouseListener:

button.addMouseListener(new MouseListener() {
    @Override
    public void mouseClicked(MouseEvent e) {
        System.out.println("Mouse click on the button!");
    }
    // The remaining methods can be left empty
    @Override public void mousePressed(MouseEvent e) {}
    @Override public void mouseReleased(MouseEvent e) {}
    @Override public void mouseEntered(MouseEvent e) {}
    @Override public void mouseExited(MouseEvent e) {}
});

Writing five empty methods for a single handler isn’t very convenient. That’s what MouseAdapter is for:

button.addMouseListener(new MouseAdapter() {
    @Override
    public void mouseClicked(MouseEvent e) {
        System.out.println("Mouse click on the button (via adapter)!");
    }
});

MouseAdapter implements all interface methods, and you override only the ones you need.

Keyboard events: KeyListener/KeyAdapter

If you need to capture key presses:

button.addKeyListener(new KeyAdapter() {
    @Override
    public void keyPressed(KeyEvent e) {
        System.out.println("Key pressed: " + e.getKeyChar());
    }
});

Text change events: DocumentListener

For text fields (JTextField, JTextArea) there are special listeners:

JTextField textField = new JTextField();
textField.getDocument().addDocumentListener(new DocumentListener() {
    @Override
    public void insertUpdate(DocumentEvent e) {
        System.out.println("Text changed: " + textField.getText());
    }
    @Override public void removeUpdate(DocumentEvent e) {}
    @Override public void changedUpdate(DocumentEvent e) {}
});

By the way, most event types have adapters so you don’t have to write empty methods.

5. Practice: a mini example with a window and a button

Let’s build the simplest GUI app: a window with a button that increments a counter and displays a message when clicked.

Example: click counter

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class ClickCounterApp {
    public static void main(String[] args) {
        JFrame frame = new JFrame("Click counter");
        JButton button = new JButton("Click me!");
        JLabel label = new JLabel("Clicks: 0");
        // Click counter (must be final or effectively final)
        final int[] count = {0};

        button.addActionListener(e -> {
            count[0]++;
            label.setText("Clicks: " + count[0]);
        });

        frame.setLayout(new FlowLayout());
        frame.add(button);
        frame.add(label);

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(250, 100);
        frame.setVisible(true);
    }
}

Explanation:

  • Create a window, a button, and a label to display the counter.
  • Use a single-element array (final int[] count = {0};) to bypass the lambda restriction on final/effectively final variables.
  • Each time the button is clicked, increment the counter and update the label text.

Practice idea: try changing the button color on every fifth click!

6. How the event model works under the hood

Let’s take a quick look under the hood. When you call:

button.addActionListener(listener);

the button (a JButton object) adds your listener to an internal list. When the user clicks the button, the following happens internally:

  1. The button creates an event object (ActionEvent).
  2. The button iterates over the list of listeners and calls actionPerformed on each of them.
  3. Your handler performs the required actions (for example, updates the label).

The main thing to remember: each event can have any number of listeners—you can add several handlers for one button; they will be invoked sequentially.

7. Visual diagram: event handling

graph TD
    A[User clicked the button] --> B{JButton}
    B --> C[Create ActionEvent]
    C --> D[Call actionPerformed on all listeners]
    D --> E[Handler performs actions]

7. Common mistakes when working with events in Swing and AWT

Error #1: forgot to register the listener. The button does not react to clicks because you forgot to call addActionListener.

Error #2: heavy work in the handler. If you start a long-running loop or download something from the internet inside the event handler, the UI will freeze. For long tasks, use separate threads or SwingWorker.

Error #3: trying to change a variable from a lambda without it being final/effectively final. Inside a lambda, you can use only final or “effectively final” variables. For counters, use arrays or special classes (such as AtomicInteger if you want to be more formal).

Error #4: forgot to remove the listener. If you remove a component but don’t remove its listener, a memory leak is possible. Unsubscribe when the component is no longer needed.

Error #5: not all interface methods are implemented. If you implement MouseListener directly, don’t forget all the methods! It’s better to use adapters (MouseAdapter, KeyAdapter).

1
Task
JAVA 25 SELF, level 50, lesson 1
Locked
Smart Home Greeting 🏡
Smart Home Greeting 🏡
1
Task
JAVA 25 SELF, level 50, lesson 1
Locked
Thermostat Activation 🌡️
Thermostat Activation 🌡️
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION