Creating a Frame
A top-level window (that is, a window that is not contained inside another window) is called a frame in Java. The AWT library has a class, called Frame, for this top level. The Swing version of this class is called JFrame that extends the Frame class. The JFrame is one of the few Swing components that is not painted on a canvas. Thus, the decorations (buttons, title bar, icons, and so on) are drawn by the user's windowing system, not by Swing.
Frames are examples of containers. This means that a frame can contain other user interface components such as buttons and text fields. In this section, we want to go over the most common methods for working with a Swing JFrame. Example 7-1 lists a simple program that displays an empty frame on the screen, as illustrated in Screenshot-4.
Most Swing component classes start with a "J": JButton, JFrame, and so on. There are classes such as Button and Frame, but they are AWT components. If you accidentally omit a "J", your program may still compile and run, but the mixture of Swing and AWT components can lead to visual and behavioral inconsistencies.
Example 7-1 SimpleFrameTest.java
1. import javax.swing.*;
3. public class SimpleFrameTest
5. public static void main(String args)
7. SimpleFrame frame = new SimpleFrame();
13. class SimpleFrame extends JFrame
15. public SimpleFrame()
17. setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
20. public static final int DEFAULT_WIDTH = 300;
21. public static final int DEFAULT_HEIGHT = 200;
Screenshot-4. The simplest visible frame
Let's work through this program, line by line. The Swing classes are placed in the javax.swing package. The package name javax indicates a Java extension package, not a core package. The Swing classes are indeed an extension to Java 1.1. Because the Swing classes were not made a part of the core hierarchy, it is possible to load the Swing classes into a Java 1.1-compatible browser. (The security manager of the browser does not allow adding any packages that start with "java.".) On the Java 2 platform, the Swing package is no longer an extension, but is instead part of the core hierarchy. Any Java implementation that is compatible with Java 2 must supply the Swing classes. Nevertheless, the javax name remains, for compatibility with Java 1.1 code. (Actually, the Swing package started out as com.sun.java.swing, then briefly got moved to java.awt.swing during early Java 2 beta versions, then went back to com.sun.java. swing in late Java 2 beta versions, and after howls of protest by Java programmers, found its final resting place in javax.swing.) By default, a frame has a rather useless size of 0 x 0 pixels. We define a subclass SimpleFrame whose constructor sets the size to 300 x 200 pixels. In the main method of the SimpleFrameTest class, we start out by constructing a SimpleFrame object. Next, we define what should happen when the user closes this frame. For this particular program, we want the program to exit. To select this behavior, use the statement
In other programs with multiple frames, you would not want the program to exit just because the user closes one of the frames. By default, a frame is hidden when the user closes it, but the program does not terminate.
The EXIT_ON_CLOSE parameter for the setDefaultCloseOperation method was introduced with version 1.3 of the Java 2 SDK. If you are using an earlier version, you need to remove this line from the source code. (You will have to do that with the majority of programs in this tutorial.) Of course, after removing the call to setDefaultCloseOperation, the program won't exit when you close the window. To exit the program, you need to kill it. Under X Windows, there is usually a menu option to "kill," "annihilate," or "destroy" the program. The details depend on the window manager. In Windows, you can summon the task list (with the CTRL+ALT+DEL "three-finger salute") and end the task. Of course, these are drastic remedies. Alternatively, you can replace the call to the setDefaultCloseOperation method with the following code:
public void windowClosing(WindowEvent e)
You will see in why this code fragment exits the app when the frame is closed.
Simply constructing a frame does not automatically display it. Frames start their life invisible. That gives the programmer the chance to add components into the frame before showing it for the first time. To show the frame, the main method calls the show method of the frame. Afterwards, the main method exits. Note that exiting main does not terminate the program, just the main thread. Showing the frame activates a user interface thread that keeps the program alive.
The preceding note told you the "official" way of making a frame close on exit in a pre-1.3 version of the Java 2 SDK. However, in some of those versions, the call
magically works as well. Apparently, the functionality for the "exit on close" behavior had been added to the SDK before the EXIT_ON_CLOSE constant was added to the JFrame class.
The running program is shown in Screenshot-4—it is a truly boring top-level window. As you can see in the figure, the title bar and surrounding decorations, such as resize corners, are drawn by the operating system and not the Swing library. If you run the same program in X Windows, the frame decorations are different. The Swing library draws everything inside the frame. In this program, it just fills the frame with a default background color.
The JFrame class inherits the show method from the superclass Window. The Window class has a superclass Component that also has a show method. The Component.show method is deprecated, and you are supposed to call setVisible(true) instead if you want to show a component. However, the Window.show method is not deprecated. For windows and frames it makes sense to call show, not setVisible, because show makes the window visible and brings it to the front.
As of SDK 1.4, you can turn off all frame decorations by calling frame.setUndecorated(true).
In the above example we wrote two classes, one to define a frame class and one that contains a main method that creates and shows a frame object. Frequently, you will see programs in which the main method is opportunistically tossed into a convenient class, like this:
class SimpleFrame extends JFrame
public static void main(String args)
SimpleFrame frame = new SimpleFrame();
public static final int DEFAULT_WIDTH = 300;
public static final int DEFAULT_HEIGHT = 200;
Using the main method of the frame class for the code that launches the program is simpler in one sense. You do not have to introduce another auxiliary class. However, quite a few programmers find this code style a bit confusing. Therefore, we prefer to separate out the class that launches the program from the classes that define the user interface.