Terminating a Program with “Window Close”

Problem

Nothing happens when you click on the close button on the title bar of an AWT Frame. When you do this on a Swing JFrame, the window disappears but the application does not exit.

Solution

Add a WindowListener ; have it exit the application.

Discussion

Main windows -- subclasses of java.awt.Window , such as (J)Frames and (J)Dialogs -- are treated specially. Unlike all other Component subclasses, Window and its subclasses are not initially visible. This is sensible, as they have to be packed or resized, and you don’t want the user to watch the components getting rearranged. Once you call a Window’s setVisible(true) method, all components inside it become visible. And you can listen for WindowEvents on a Window.

The WindowListener interface contains a plenitude of methods to notify a listener when anything happens to the window. You can be told when the window is activated (gets keyboard and mouse events) or deactivated. Or you can find out when the window is iconified or de-iconified: these are good times to suspend and resume processing, respectively. You can be notified the first time the window is opened. And, most importantly for us, you can be notified when the user requests that the window be closed. (Some sample close buttons are show in Figure 13-4.) The windowClosing method of your WindowListener is called when the user clicks on the close button (this depends on the window system and, on X Windows, on the window manager) or sends the close message from the keyboard (normally Alt-F4).

Some close buttons

Figure 13-4. Some close buttons

The method signature is:

public void windowClosing(WindowEvent);

But this method comes from the interface WindowListener, which has half a dozen other methods. If you define a WindowListener and implement only this one method, the compiler will declare your class abstract and refuse to instantiate it. You might start by writing stub or dummy versions (methods whose body is just the two characters {}), but you’d then be doing more work than necessary, since there’s already an “adapter” class that does this for all methods in the Listener interface. So you really need only to subclass from WindowAdapter , and override the one method, windowClosing , that you care about. Figure 13-5 shows this model.

WindowListener, WindowAdapter, and my WindowCloser

Figure 13-5. WindowListener, WindowAdapter, and my WindowCloser

Let’s put this all together in some code examples. Class WindowDemo puts up a frame and, when you ask it to close, it does so. The online source includes class WindowDemo2, which is the same, but implemented as a Swing JFrame.

import java.awt.*;
import java.awt.event.*;

/* Show an example of closing a Window.
 */
public class WindowDemo extends Frame {

    public static void main(String[] argv) {
        Frame f = new WindowDemo(  );
        f.setVisible(true);
    }
    public WindowDemo(  ) {
        setSize(200, 100);
        addWindowListener(new WindowDemoAdapter(  ));
    }

    /** Named Inner class that closes a Window. */
    class WindowDemoAdapter extends WindowAdapter {
        public void windowClosing(WindowEvent e) {
                System.out.println("Goodbye!");
                WindowDemo.this.setVisible(false);    // window will close
                WindowDemo.this.dispose(  );        // and be freed up.
                System.exit(0);
        }
    }
}

Since making a Window close -- and optionally exit the program -- is a common operation, I’ve encapsulated this into a small class called WindowCloser , which I’ve put into my public package com.darwinsys.util. Most AWT and Swing books have similar classes. Example 13-3 contains my WindowCloser class.

Example 13-3. WindowCloser.java

package com.darwinsys.util;

import java.awt.Window;
import java.awt.event.*;

/** A WindowCloser - watch for Window Closing events, and
 * follow them up with setVisible(false) and dispose(  ).
 */
public class WindowCloser extends WindowAdapter {
    /** The window we close */
    Window win;
    /** True if we are to exit as well. */
    boolean doExit = false;

    public WindowCloser(Window w) {
        this(w, false);
    }
    public WindowCloser(Window w, boolean exit) {
        win = w;
        doExit = exit;
    }
    public void windowClosing(WindowEvent e) {
        win.setVisible(false);
        win.dispose(  );
        if (doExit)
            System.exit(0);
    }
}

Using it is straightforward:

import java.awt.*;
import java.awt.event.*;

/* Show an example of closing a Window.
 */
public class WindowCloserDemo {

    /* Main method */
    public static void main(String[] argv) {
        Frame f = new Frame("Close Me");
        f.add(new Label("Try Titlebar Close", Label.CENTER));
        f.setSize(100, 100);
        f.setVisible(true);
        f.addWindowListener(new WindowCloser(f, true));
    }
}

See Also

I’ve mentioned dispose( ) several times without saying much about it. The dispose( ) method (inherited from Window) causes the underlying (operating system-specific) window system resources to be released without totally destroying the Window. If you later call pack( ) or setVisible(true) on the Window, the native resources will be re-created. It’s a good idea to dispose( ) a window if you won’t be using it for a while, but not if there’s a good chance you’ll need it again soon.

There may be cases in which you don’t even need a window closer. The Swing JFrame has a setDefaultCloseOperation( ) method, which controls the default behavior. You can pass it one of the values defined in the WindowConstants class:

WindowConstants.DO_NOTHING_ON_CLOSE

Ignore the request.

WindowConstants.HIDE_ON_CLOSE

Hide the window (default).

WindowConstants.DISPOSE_ON_CLOSE

Hide and dispose the window.

WindowConstants.EXIT_ON_CLOSE

JDK 1.3 (and later!). Exit the application on close, obviating the need for a WindowListener!

The action set by setDefaultCloseOperation( ) will be performed after your actionPerformed( ) method (the last, if more than one) returns.

There are several other multi-method interfaces, including MouseListener and ComponentListener, and an Adapter class for each of these.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.118.20.231