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.
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).
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.
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)); } }
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.
18.118.20.231