Recipe 14.6 Terminating a Program with


Recipe 14.6 Terminating a Program with"Window Close"

Problem

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

Solution

Use JFrame's setDefaultCloseOperation( ) method or add a WindowListener and 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. 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 deiconified: 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 shown in Figure 14-4.) You can respond in two ways. With Swing's JFrame, you can set the "default close operation." Alternatively, with any Window subclass, you can provide a WindowListener to be notified of window events.

In some cases, you may not 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 Swing WindowConstants class:


WindowConstants.DO_NOTHING_ON_CLOSE

Ignore the request. The window stays open. Useful for critical dialogs; probably antisocial for most "main application"-type windows.


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! Does not give you a chance to save data; for that, you need a WindowListener.

The action set by setDefaultCloseOperation( ) will be performed after the last windowClosing( ) method on the Window (if you have one) returns.

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).

Figure 14-4. Some close buttons
figs/jcb2_1404.gif


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 declares your class abstract and refuses 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; an "adapter" class already 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 14-5 shows this model.

Figure 14-5. WindowListener, WindowAdapter, and my WindowCloser
figs/jcb2_1405.gif


Let's put this all together in some code examples. Class WindowDemo puts up a frame and closes when you ask it to. 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 is in my public package com.darwinsys.util. Most AWT and Swing books have similar classes. Example 14-3 contains my WindowCloser class. Note that the class is marked deprecated; this is to remind you that, on Swing, you should just use setDefaultCloseOperation( ). If you're writing an AWT-only application, you'll have to live with the deprecation warning.

Example 14-3. WindowCloser.java
package com.darwinsys.swingui; import java.awt.Window; import java.awt.event.*; /** A WindowCloser - watch for Window Closing events, and  * follow them up with setVisible(false) and dispose( ).  * @deprecated Use setDefaultCloseOperation( ) instead.  */ public class WindowCloser extends WindowAdapter {     /** True if we are to exit as well. */     boolean doExit = false;     public WindowCloser( ) {     public WindowCloser(Window w) {         // nothing to do     }     public WindowCloser(Window w, boolean exit) {         doExit = exit;     }     public void windowClosing(WindowEvent e) {         Window win = e.getWindow( );         win.setVisible(false);         win.dispose( );         if (doExit)             System.exit(0);     } }

Using it is straightforward:

import java.awt.Frame; import java.awt.Label; import com.darwinsys.swingui.WindowCloser; /* Show an example of closing a Window.  */ public class WindowCloserTest {     /* 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));     } }

Notice that some of this "quick and dirty" class extends Frame or JFrame directly. It is generally better to have a main program that creates a JFrame and installs the "main" GUI component into that. This scheme promotes greater reusability. For example, if your graphing program's main component extends JComponent, it can be added to a JPanel in another application; whereas if it extends JFrame, it cannot.

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 are recreated. 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.

In addition to WindowListener, Swing has several other multimethod interfaces, including MouseListener and ComponentListener, and an Adapter class for each of these.



Java Cookbook
Java Cookbook, Second Edition
ISBN: 0596007019
EAN: 2147483647
Year: 2003
Pages: 409
Authors: Ian F Darwin

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net