Of course! Let's dive deep into the WindowListener interface in Java. This is a fundamental part of building graphical user interfaces (GUIs) using the Swing or AWT libraries.

What is a WindowListener?
A WindowListener is an interface in the java.awt.event package that allows you to listen for events related to a Window object. In Swing, this includes JFrame, JDialog, and JWindow.
Think of it as a security guard for your window. This "guard" watches for specific actions and can react to them. The actions (events) it listens for are:
- Opening (
windowOpened) - Closing (
windowClosing) - Closed (
windowClosed) - Iconified (minimized,
windowIconified) - De-iconified (restored from being minimized,
windowDeiconified) - Activated (gains focus,
windowActivated) - Deactivated (loses focus,
windowDeactivated)
The Interface and its Methods
The WindowListener interface has seven methods, one for each event:
public interface WindowListener extends EventListener {
// Called after the window has been opened.
void windowOpened(WindowEvent e);
// Called when the user attempts to close the window (e.g., clicks the 'X').
void windowClosing(WindowEvent e);
// Called after the window has been closed.
void windowClosed(WindowEvent e);
// Called when the window is changed to an icon (minimized).
void windowIconified(WindowEvent e);
// Called when the window is restored from an icon.
void windowDeiconified(WindowEvent e);
// Called when the window is set to be the active window.
void windowActivated(WindowEvent e);
// Called when the window is no longer the active window.
void windowDeactivated(WindowEvent e);
}
Key Distinction: windowClosing vs. windowClosed
This is a very common point of confusion and is crucial to understand:

windowClosing: This event is fired when the user tries to close the window. At this point, the window is still visible. You can use this event to ask the user "Are you sure you want to exit?" before actually closing the application.windowClosed: This event is fired after the window has been successfully closed and removed from the screen. You cannot interact with the window at this point.
How to Use a WindowListener
There are three main ways to use a WindowListener:
- Implementing the Interface (The "Classic" Way)
- Using an Anonymous Inner Class (The Common Way)
- Using a Lambda Expression (The Modern, Java 8+ Way)
Let's look at examples for each.
Setup: A Simple JFrame
First, let's create a basic JFrame that we will add our listeners to.
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
public class MyWindow {
public static void main(String[] args) {
// Ensure the GUI is created on the Event Dispatch Thread (EDT)
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame("WindowListener Demo");
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); // See explanation below
frame.setSize(400, 300);
frame.setLocationRelativeTo(null); // Center the window
frame.add(new JLabel("Try closing, minimizing, and focusing this window."));
// We will add the listener here in the examples below
// addWindowListener(frame);
frame.setVisible(true);
});
}
}
Note: We set
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE). This is important because if we useJFrame.EXIT_ON_CLOSE, the program will exit immediately when the 'X' is clicked, and ourwindowClosinglistener will never have a chance to run. We will handle the closing logic manually in our listener.(图片来源网络,侵删)
Method 1: Implementing the Interface
This approach involves creating a separate class that implements WindowListener and then creating an instance of that class to add to the frame.
Pros:
- Keeps the listener logic separate and reusable.
- Good for complex listeners.
Cons:
- Can be verbose (boilerplate code).
// 1. Create a class that implements the interface
class MyWindowListener implements WindowListener {
@Override
public void windowOpened(WindowEvent e) {
System.out.println("Window opened.");
}
@Override
public void windowClosing(WindowEvent e) {
System.out.println("Window is closing...");
// Ask for confirmation before exiting
int option = javax.swing.JOptionPane.showConfirmDialog(
null,
"Are you sure you want to exit?",
"Confirm Exit",
javax.swing.JOptionPane.YES_NO_OPTION
);
if (option == javax.swing.JOptionPane.YES_OPTION) {
// Dispose the window to close it
e.getWindow().dispose();
}
}
@Override
public void windowClosed(WindowEvent e) {
System.out.println("Window closed.");
// If this is the main window, you might want to exit the application
System.exit(0);
}
@Override
public void windowIconified(WindowEvent e) {
System.out.println("Window minimized.");
}
@Override
public void windowDeiconified(WindowEvent e) {
System.out.println("Window restored.");
}
@Override
public void windowActivated(WindowEvent e) {
System.out.println("Window activated.");
}
@Override
public void windowDeactivated(WindowEvent e) {
System.out.println("Window deactivated.");
}
}
// In your main class, you would use it like this:
// MyWindowListener listener = new MyWindowListener();
// frame.addWindowListener(listener);
Method 2: Using an Anonymous Inner Class
This is the most common pre-Java 8 way to handle listeners. It allows you to implement the interface and create an instance in one go, keeping the code localized.
// In your main method, after creating the frame:
frame.addWindowListener(new WindowListener() {
@Override
public void windowOpened(WindowEvent e) {
System.out.println("Window opened.");
}
@Override
public void windowClosing(WindowEvent e) {
System.out.println("Window is closing...");
int option = javax.swing.JOptionPane.showConfirmDialog(
null,
"Are you sure you want to exit?",
"Confirm Exit",
javax.swing.JOptionPane.YES_NO_OPTION
);
if (option == javax.swing.JOptionPane.YES_OPTION) {
e.getWindow().dispose();
}
}
@Override
public void windowClosed(WindowEvent e) {
System.out.println("Window closed.");
System.exit(0);
}
@Override
public void windowIconified(WindowEvent e) {
System.out.println("Window minimized.");
}
@Override
public void windowDeiconified(WindowEvent e) {
System.out.println("Window restored.");
}
@Override
public void windowActivated(WindowEvent e) {
System.out.println("Window activated.");
}
@Override
public void windowDeactivated(WindowEvent e) {
System.out.println("Window deactivated.");
}
});
Method 3: Using a Lambda Expression (Java 8+)
This is the modern, most concise, and often preferred way. Since most of the methods in WindowListener are only used once, lambdas are a perfect fit. You can use the WindowAdapter (see next section) for an even cleaner approach, but you can also implement the full interface.
// In your main method, after creating the frame:
frame.addWindowListener(new WindowListener() {
@Override
public void windowClosing(WindowEvent e) {
// We only care about the closing event for this example
System.out.println("Window is closing via Lambda...");
int option = javax.swing.JOptionPane.showConfirmDialog(
null,
"Are you sure you want to exit?",
"Confirm Exit",
javax.swing.JOptionPane.YES_NO_OPTION
);
if (option == javax.swing.JOptionPane.YES_OPTION) {
e.getWindow().dispose();
}
}
// Provide empty implementations for the rest
@Override public void windowOpened(WindowEvent e) {}
@Override public void windowClosed(WindowEvent e) { System.exit(0); }
@Override public void windowIconified(WindowEvent e) {}
@Override public void windowDeiconified(WindowEvent e) {}
@Override public void windowActivated(WindowEvent e) {}
@Override public void windowDeactivated(WindowEvent e) {}
});
A Better Alternative: WindowAdapter
Implementing all seven methods is often tedious if you only care about one or two events. Java provides a convenience class called java.awt.event.WindowAdapter that provides default (empty) implementations for all WindowListener methods.
You can then extend this class and only override the methods you need.
Example using WindowAdapter with an Anonymous Inner Class:
This is cleaner than implementing the full interface.
// In your main method, after creating the frame: frame.addWindowListener(new Window

