You are on page 1of 77

??

Chapter 13

Java Swing (optional)

Chapter Preview
Java is a ne programming language, yet it is not for that
alone that it has generated so mu h ex itement, but for its
potential role in animating the World Wide Web. In this
hapter we dis uss the meaning of that role, and begin to
show how you an animate your own small part of the web
by writing applets in Java. We rst introdu e Java graphi al
omponents, in luding text elds, buttons, and s roll bars,
and we show how Java programs an be made to rea t to
users' a tions upon those omponents. By doing this, we will
no longer have to rely on the CSLib pa kage to write graph-
i al programs. We further show how the Java appli ations
that we've written an be run from within web browsers.
The fundamental things apply,
As time goes by.
|Herman Huupfeld
\As Time Goes By"

Suit the a tion to the word, the word to the a tion.


|William Shakespeare
Hamlet

The Java system omes with ertain prede ned methods su h


as Math.sqrt(double d). The lasses and methods provided with
the Java ompiler (or any ompiler for any language) are alled the
appli ation appli ation programming interfa e (API). The API is provided to make
programming it easier to program appli ations and applets. The Java API onsists of
interfa e a large olle tion of lasses (several hundred), ea h with many methods.
pa kages All are organized into pa kages. The Java API in ludes over 36 pa k-
ages, at last ount. They ontain lasses and methods for everything
from generating random numbers to loading sound les to a essing
Internet sites.

13.1 The Java Swing omponents

We have seen how java.awt and java.awt.event appeared in the


import statements in some of our appli ations. Those import state-
ments were in luded so that all the lasses in those pa kages would be
available to our appli ation.
There is a reason why we did not expli itly import the java.lang
pa kages. This is the only pa kage that is automati ally imported in
every Java program; saying import java.lang.* would be redundant.
This pa kage ontains lasses like Math and String, whi h are so basi
that everyone will use them frequently.
The java.awt and java.awt.event pa kages are another matter.
We have often used the Point lass from java.awt, but other than that
we have used these lasses very little. The java.awt.event pa kage
2
13.1. THE JAVA SWING COMPONENTS 3

was used only in the optional Chapter 11. We'll use many more of their
lasses in this hapter. But most of all, we will use another pa kage,
javax.swing. The lasses in this pa kage are used to reate all sorts
of stu that one normally asso iates with graphi al user interfa es- graphi al user interfa es
(GUIs): buttons, menus, text areas, s roll bars, and so on. Ea h of omponents
these items, alled omponents, has an asso iated lass. The pa kage
java.awt.event ontains lasses that allow us to intera t with the
graphi al omponents, just as it ontained lasses allowing us to at h
mouse events.
There are two important omponents that we have already seen
indire tly { the Frame and the Dialog omponents. Our CSLib's
DrawingBox and OutputBox are really variants of Frame, while our
InputBox and ErrorBox are variants of Dialog.
Until now, we have relied on the DrawingBox lass from the CSLib
pa kage for writing graphi al programs. However, real Java graphi al
programs require mu h more powerful pa kages and lasses. The lass
that we will use in pla e of our DrawingBox is Java's JFrame lass.
JFrame is very similar to Frame (see bug alert ??).

Remember the J.
In this hapter, we are overing the so- alled Swing om-
ponents, whi h in lude JFrame, JButton, JS rollBar, and
many others.
Why the \J"? There is another set of omponents in
java.awt itself, with names Frame, Button, et . These om-
ponents | the \abstra t windowing toolkit," or \AWT,"
omponents | were introdu ed rst and took the good
names. The later Swing omponents had to use di erent
names, so the J was added.
Some of the di eren es between the AWT omponents and
the Swing omponents are dis ussed in se tion ?? of this
hapter. The important thing to know now is that you should
use only the Swing omponents in your programs | mixing
AWT and Swing omponents is asking for trouble. So, don't
forget the J!
By the way, you may wonder why we import java.awt in our
programs if we are not going to use AWT omponents. As
with almost everything related to omputers, there are ex ep-
tions to the above rule: o asionally, AWT omponents must
be used. We will point these out as we pro eed. Further,
java.awt ontains numerous useful lasses that are not om-
ponents, su h as Color, Font, and Point. We will ontinue
to use those lasses.
Bug Alert 13.1
4 CHAPTER 13. JAVA SWING (OPTIONAL)

A JFrame is a window with a title bar and a border. A typi-


al Java GUI appli ation will reate and display one or more JFrames,
often arranging other omponents inside these JFrames. A JFrame
is initially not visible; your program must make it visible by send-
ing the setVisible(true) message to it. A JFrame obje t ontains
a Container obje t, whi h an be obtained by sending the JFrame
the getContentPane() message. Container is a lass in java.awt; a
Container is a omponent that ontains other omponents, whi h are
pla ed into it via the add method. One omponent that an be added
to a Container is the JButton omponent. A JButton has a label, and
an be \ li ked on" by the user, appearing to depress and pop ba k.
For example, you an reate and pla e a pair of buttons in a frame
as follows:
1 JFrame f = new JFrame("Two Buttons Frame");
2 JButton redButton = new JButton("Red");
3 JButton blueButton = new JButton("Blue");
4 Container p = f.getContentPane();
5 p.setLayout(new FlowLayout());
6 p.add(redButton);
7 p.add(blueButton);
8 f.setVisible(true);
In line 1 we reate a JFrame, passing a string to the onstru tor for the
title of the JFrame (just as with CSLib's DrawingBox). In lines 2 and 3
we reate two JButtons; the string argument gives the label that will
appear on the button. We obtain the ontent pane of the JFrame and
then (skipping line 5 for the moment), we add the two buttons to that
ontainer. Lastly, we make the frame visible.1
We now have only to explain line 5. How exa tly are omponents
added to a Container? Are they sta ked one on top of the other? Are
they arranged in random lo ations within the Frame? The answer is
LayoutManager that there is a LayoutManager obje t that governs how omponents
are arranged within a Container. The Container lass has a method
setLayout(LayoutManager) that allows the programmer to spe ify a
parti ular LayoutManager. This is the purpose of line 5. It instru ts
FlowLayout the frame to use the FlowLayout manager. The FlowLayout manager
uses a simple approa h to omponent layout: it arranges added om-
ponents in a line from left to right, owing to the next line as needed.
Just as we saw with DrawingBox and OutputBox, we an set the
size of a JFrame by using the setSize (int width, int height)
method. Indeed, if we fail to set the size of a Container, then it
shows up as a very small window, too small to show its ontained om-
ponents. So here's the omplete program, with the frame size set and
a layout manager spe i ed:

1 Using the Swing omponents is a bit more ompli ated than using CSLib. That is, of
ourse, exa tly why we wrote CSLib!
13.1. THE JAVA SWING COMPONENTS 5

1 import javax.swing.*;
2 import java.awt.*;
3
4 publi lass TwoButtons {
5 JFrame f;
6 JButton redButton, blueButton;
7
8 publi TwoButtons () {
9 f = new JFrame("Two Buttons Frame");
10 redButton = new JButton("Red");
11 blueButton = new JButton("Blue");
12 Container p = f.getContentPane();
13 p.setLayout(new FlowLayout());
14 p.add(redButton);
15 p.add(blueButton);
16 f.setSize(150, 70);
17 f.setVisible(true);
18 }
19 }

Running this program results in the following output.

We ould obtain a perfe t size for the JFrame by doing the kinds
of experiments that you did in the last qui k exer ise. But there is an
elegant way to adjust the size of a ontainer to be just large enough
to a ommodate its ontained omponents, without guesswork. Ev-
ery omponent has a preferred size. By sending to a JFrame the preferred size
pa k() message, it will be resized to be just large enough to hold pa k()
all of its omponents set to their preferred sizes. In addition to meth-
6 CHAPTER 13. JAVA SWING (OPTIONAL)

To see how resizing the window works, run the above pro-
gram with the setSize all omitted; then with the size set
to 50 by 50; then with the size set to 50 by 100. As another
experiment, omit the setLayout all; the results here will be
surprising; we will explain them in se tion ??.
Qui k Exer ise 13.1

Be sure to make the frame visible.


A JFrame is not visible until it re eives the
setVisible(true) message.
Bug Alert 13.2

ods for setting and getting a Component's a tual size, there are methods
setPreferredSize(...) and getPreferredSize(...) for manipulat-
ing a Component's preferred size. For a JButton, the default preferred
size is just large enough to ontain the JButton's label. Here's a om-
plete appli ation in orporating these on epts.

1 import javax.swing.*;
2 import java.awt.*;
3
4 publi lass TwoButtons {
5 JFrame f;
6 JButton redButton, blueButton;
7
8 publi TwoButtons () {
9 f = new JFrame("Two Buttons Frame");
10 redButton = new JButton("Red");
11 blueButton = new JButton("Blue");
12 Container p = f.getContentPane();
13 p.setLayout(new FlowLayout());
14 p.add(redButton);
15 p.add(blueButton);
16 f.pa k();
17 f.setVisible(true);
18 }
19 }

Running this program results in the following output.


13.1. THE JAVA SWING COMPONENTS 7

If you li k on either of the buttons, they appear to \depress" as buttons


normally do, but of ourse, there is no a tion that is taken. We must
program them to perform some sort of a tion. We'll see how to do that
just a bit later in this hapter.

Be sure to pa k the JFrame, or set its size.


If you don't set the size of the frame, then it may be too small
to show the omponents that it ontains. Alternatively, you
may pa k the frame; this will usually produ e a frame of
appropriate size.
Bug Alert 13.3

A lass diagram is shown in Figure 13.1. It shows that the TwoButtons


lass ontains one JFrame and two JButton obje ts. However, it does
not show all of the details that we know about these and other lasses.
For example, the methods are not expli itly shown, nor are the super
lasses (like Component and Container) shown. A good UML diagram
should show only the lasses and asso iations that are important to
understanding things; extraneous lasses and relationships would just
lutter the diagram.
8 CHAPTER 13. JAVA SWING (OPTIONAL)

UML diagram to be supplied


FIGURE 13.1: A UML lass diagram for the TwoButtons program.
Name Des ription
JButton () Constru ts a new button.
JButton (String l) Constru ts a new button with label l.
JButton (I on i) Constru ts a new button with i on i.
String getText () Gets the label for this button.
void setText (String l) Sets the label of this button to l.
void addA tionListener Makes l a listener for a tion events from this
button.
(A tionListener l)

TABLE 13.1: Some methods of the JButton lass. Other methods


are inherited from JComponent. addA tionListener is explained in
Se tion 13.3.

13.1.1 Enhan ing the appearan e of buttons

Methods of the JButton lass are given in Table 13.1; the JComponent
lass, from whi h it inherits, is do umented in Table 13.2. Many of
these methods serve to hange the appearan e of the button: its olor,
font, and so on. These methods are also de ned for other omponent
lasses, so we an illustrate them with JButton.
foreground olor A button has a foreground olor used for the text itself and a
ba kground olor ba kground olor used for the rest of the button. The Color lass in
java.awt has onstants Color.red, Color.blue, et .
The Font lass in java.awt an be used to reate font obje ts,
whi h an then be used to render the text in a omponent by sending
font family the omponent the setFont message. \Helveti a" is the name of a font
typefa e family or typefa e, whi h in ludes hara ters with a ommon look in
various sizes and styles (su h as itali and bold). \Courier" is another
typefa e.
This version of TwoButtons draws the text of the buttons in red
Helveti a and blue Courier, respe tively, on a gray ba kground:
1 import javax.swing.*;
2 import java.awt.*;
3
4 publi lass TwoButtons {
5 JFrame f;
6 JButton redButton, blueButton;
7
8 publi TwoButtons () {
9 f = new JFrame("Two Buttons Frame");
13.1. THE JAVA SWING COMPONENTS 9

Name Des ription


void addMouseListener Makes l a listener for mouse events from this
(MouseListener l) omponent.
void addMouseMotionListener Makes l a listener for mouse motion events
(MouseMotionListener l) from this omponent.
Color getBa kground () Get the ba kground olor of this omponent.
Font getFont () Get the font of this omponent.
FontMetri s getFontMetri s Get the font metri s for the font f.
(Font f)
Color getForeground () Get the foreground olor for this omponent.
Graphi s getGraphi s () Get the graphi s ontext for this omponent.
int getHeight () Get the height of this omponent.
Dimension getMinimumSize () Get the minimum size of this omponent.
Dimension getPreferredSize () Get the preferred size of this omponent.
Dimension getSize () Get the size of this omponent.
int getWidth () Get the width of this omponent.
void paintBorder (Graphi s g) Paint this omponent's border.
void paintComponent (Graphi s Paint this omponent (and its sub ompo-
g) nents).
void repaint () Request a repaint of this omponent.
void setFont (Font f) Set the font of this omponent.
void setForeground (Color ) Set the foreground of this omponent.
void setSize (int w, int h) Set the size of this omponent.
void setSize (Dimension d) Alternate version of setSize.
void setVisible (boolean b) Shows or hides this omponent depending on
b.
String toString () Stringify this omponent.

TABLE 13.2: Some methods of the JComponent lass. Some of these


methods are inherited from the super lass java.awt.Container, or its
super lass, java.awt.Component.
10 CHAPTER 13. JAVA SWING (OPTIONAL)

Name Des ription


stati int BOLD The bold style.
stati int ITALIC The itali style.
stati int PLAIN The plain style.
Font (String name, int style, Create a new font with the given name, style,
int size) and size.
String getFamily () Return the family name for this font.
int getStyle () Return the style for this font.
String getFontName () Return the fa e name for this font.
String getName () Return the name for this font.
int getSize () Return the size for this font.
boolean isBold () Indi ate whether this font is bold.
boolean isItali () Indi ate whether this font is itali .
boolean isPlain () Indi ate whether this font is plain.
String toString () Stringify this font.

TABLE 13.3: Some onstants and methods of the Font lass.

10
11 redButton = new JButton("Red");
12 redButton.setForeground(Color.red);
13 redButton.setBa kground(Color.gray);
14 redButton.setFont(new Font("Helveti a", Font.PLAIN, 14));
15
16 blueButton = new JButton("Blue");
17 blueButton.setForeground(Color.blue);
18 blueButton.setBa kground(Color.gray);
19 blueButton.setFont(new Font("Courier", Font.BOLD, 18));
20
21 Container p = f.getContentPane();
22 p.setLayout(new FlowLayout());
23 p.add(redButton);
24 p.add(blueButton);
25 f.pa k();
26 f.setVisible(true);
27 }
28 }

In line 14, we ask for the plain style of Helveti a in size 14 ( alled
point\14 points," a point being a length used by typographers, equal to
approximately 721 of an in h). In line 19, we ask for the bold style of
Courier in 18-point size. The Font lass is summarized in Table 13.3.
i on The label on a button an in lude a small image | alled an i on
| instead of, or in addition to, the text. An i on is any obje t of a lass
that implements the I on interfa e, shown in Figure 13.4. One su h
lass, provided in the Swing pa kage, is ImageI on. (Note that this
name does not start with a J; even though it is in the Swing pa kage,
13.1. THE JAVA SWING COMPONENTS 11

Method Purpose
void paintI on(Component , Graphi s g, draw i on at lo ation (x,y).
int x, int y)
int getI onWidth() return i on's width, in pixels.
int getI onHeight() return i on's width, in pixels.

TABLE 13.4: The I on interfa e.

it does not ompete with any name in the AWT pa kage, so the J is
not needed.) Its onstru tor
ImageI on (String filename)

reates an i on from the lename of a GIF or JPEG le.


Suppose the les left1 and right1 ontain these images:

This version of TwoButtons:


1 import javax.swing.*;
2 import java.awt.*;
3
4 publi lass TwoButtons {
5 JFrame f;
6 JButton leftButton, rightButton;
7
8 publi TwoButtons () {
9 f = new JFrame("Two Buttons Frame");
12 CHAPTER 13. JAVA SWING (OPTIONAL)

10
11 ImageI on leftarrow = new ImageI on("left1.gif");
12 leftButton = new JButton(leftarrow);
13 leftButton.setBorder(null);
14
15 ImageI on rightarrow = new ImageI on("right1.gif");
16 rightButton = new JButton(rightarrow);
17 rightButton.setBorder(null);
18
19 Container p = f.getContentPane();
20 p.setLayout(new FlowLayout());
21 p.add(leftButton);
22 p.add(rightButton);
23 f.pa k();
24 f.setVisible(true);
25 }
26 }

produ es this frame:

We have made one other hange we didn't mention earlier: we elimi-


nated the borders surrounding ea h i on by in luding the message send
leftButton.setBorder(null), and likewise for rightButton.
As our nal enhan ement of the buttons, we an hange the way
a button appears when it is pressed or when the ursor rolls over it.
This is an e e t you have undoubtedly seen on web pages. If you
roll the mouse over the buttons in TwoButtons, their appearan e does
not hange at all; if you press on the buttons, again nothing hap-
pens. Now suppose we have les left2.gif, left3.gif, right2.gif,
13.1. THE JAVA SWING COMPONENTS 13

right3.gif:

We an make these the \rolled over" and \pressed" i ons for the
two buttons:
1 import javax.swing.*;
2 import java.awt.*;
3
4 publi lass TwoButtons {
5 JFrame f;
6 JButton leftButton, rightButton;
7
8 publi TwoButtons () {
9 f = new JFrame("Two Buttons Frame");
10
11 ImageI on leftarrow = new ImageI on("left1.gif");
12 leftButton = new JButton(leftarrow);
13 leftButton.setBorder(null);
14 ImageI on leftarrowdown = new ImageI on("left2.gif");
15 leftButton.setPressedI on(leftarrowdown);
16 ImageI on leftarrowover = new ImageI on("left3.gif");
17 leftButton.setRolloverI on(leftarrowover);
18 leftButton.setRolloverEnabled(true);
19
20 ImageI on rightarrow = new ImageI on("right1.gif");
21 rightButton = new JButton(rightarrow);
22 rightButton.setBorder(null);
23 ImageI on rightarrowdown = new ImageI on("right2.gif");
24 rightButton.setPressedI on(rightarrowdown);
14 CHAPTER 13. JAVA SWING (OPTIONAL)

25 ImageI on rightarrowover = new ImageI on("right3.gif");


26 rightButton.setRolloverI on(rightarrowover);
27 rightButton.setRolloverEnabled(true);
28
29 Container p = f.getContentPane();
30 p.setLayout(new FlowLayout());
31 p.add(leftButton);
32 p.add(rightButton);
33 f.pa k();
34 f.setVisible(true);
35 }
36 }

There is yet another form of the button i on that an be


used: a grayed-out version indi ating that the button may
not be used at this time. If you send the button the message
setEnabled(false), it will produ e su h a grayed-out ver-
sion; try this. If you would like a spe ial i on to be used when
the button is disabled, use setDisabledI on(I on i); nd
a graphi and try using it as the disabled i on.
Qui k Exer ise 13.2

13.2 Using Inheritan e

Noti e that in the TwoButtons program, the lient reates an instan e


of the TwoButtons lass, whi h in turn reates an instan e of a JFrame.
By using inheritan e, we an ause the TwoButtons lass itself to be
the frame. So the lient an reate an instan e of a TwoButtons,
whi h would itself be a JFrame. Thereafter, the TwoButtons onstru -
tor would add omponents to itself. The e e t is that the lient no
longer has to worry about reating a separate JFrame. Rather, the
TwoButtons lass has all of the hara teristi s that are desired. This
ode has the same e e t as the earlier version:
1 import javax.swing.*;
2 import java.awt.*;
3
4 publi lass TwoButtons extends JFrame {
5 JButton redButton, blueButton;
6
7 publi TwoButtons () {
8 super("Two Buttons Frame");
13.3. THE JAVA AWT EVENT MODEL 15
UML diagram to be supplied
FIGURE 13.2: A UML lass diagram for the alternative TwoButtons
program.

9 redButton = new JButton("Red");


10 blueButton = new JButton("Blue");
11 Container p = getContentPane();
12 p.setLayout(new FlowLayout());
13 p.add(redButton);
14 p.add(blueButton);
15 pa k();
16 setVisible(true);
17 }
18 }

In line 4 we see that lass TwoButtons extends lass JFrame. In


line 8 we see the use of super to set the super lass JFrame's title (see
Se tion ?? on page ??). Throughout the body of the onstru tor,
where we previously sent messages to an instantiated frame, f, we now
send the messages to the TwoButtons obje t itself. Another way of
viewing this is that the TwoButtons instan e sends messages to this
impli itly. It is often onfusing to the novi e to see the TwoButtons
onstru tor sending messages to the instan e that it is onstru ting!
However, this me hanism is used often in Java { a new obje t already
exists when a onstru tor is entered; it is referen ed by \this."
The UML lass diagram for our new TwoButtons program is shown
in Figure 13.2. This time, TwoButtons is a sub lass of JFrame, and as
su h, TwoButtons ontains the JButtons.

Modify this last version of TwoButtons in the same ways as


we did earlier: hange the olor of the buttons' text; use i ons
instead of text; and add roll-over and pressed i ons.
Qui k Exer ise 13.3

13.3 The Java AWT Event Model

Components should do more than just take up spa e in your program's


window. Cli king on a button should ause something to happen. This
is where the pa kage java.awt.event omes in; its lasses de ne var-
ious types of events, su h as the event of a user li king on a button.
16 CHAPTER 13. JAVA SWING (OPTIONAL)

Method Purpose
void a tionPerformed (A tionEvent e) alled when any a tion event o urs

TABLE 13.5: The A tionListener interfa e. A tion events are gen-


erated by buttons and text elds. (Text elds are introdu ed in se -
tion 13.4.)

Rea tive omponents work very similarly to the mouse events that we
saw in Chapter 11. The major di eren e is that the mouse is not
aÆliated with any on-s reen artifa t, whereas buttons are.
To in lude a rea tive JButton in a program, the basi steps are:
1. Import the java.awt.event pa kage.
2. In the lass heading, the program de lares itself to implement
the A tionListener interfa e. The A tionListener interfa e is
shown in Table 13.5.
3. Typi ally in the onstru tor, on e the JButton has been reated,
\this" obje t registers itself as being interested in listening for
events from the JButton.
4. The one method of the A tionListener interfa e (namely
a tionPerformed) is de ned. The A tionEvent argument an
be used to nd out more about the event. The method
a tionPerformed is invoked when the event (a button press) o -
urs.
These steps are summarized in Figure 13.3.
On e again, a UML lass diagram is useful for illustrating the as-
so iations between lasses. The UML diagram for the skeletal ode of
Figure 13.3 is shown in Figure 13.4. The UML generalization and
omposition asso iations are just as they were for the se ond ver-
sion of TwoButtons. But this time, we in lude additional information
about Java events. We see that JButton has a \generates" asso ia-
tion with A tonEvents; the A tionEvents in turn are \listened for"
by the lassname. Finally, in order for lassname to be able to ful-
ll its role as an event listener, it must implement the Java interfa e
A tionListener. A UML notation for a Java interfa e is indi ated by
UML implements itali izing the interfa e name; the implements asso iation is indi ated
asso iation by a dashed line with a losed, un lled arrowhead at the abstra t lass
end. We ould have just an hored the tail of this \implements" as-
so iation at the edge of lassname. But here we an provide just a
little more information|we group the methods of lassname, and an-
hor the tail of the \implements" asso iation near the method(s) that
13.3. THE JAVA AWT EVENT MODEL 17

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

:::

publi lass lassname extends JFrame implements A tionListener f


:::

JButton buttonname;
:::

publi lassname () f
:::

buttonname = new JButton("button label");


:::

Container p = getContentPane();
p.add( buttonname);
:::

buttonname.addA tionListener(this);
:::

:::

publi void a tionPerformed (A tionEvent e) f


::: what to do when buttonname is pushed :::

g
g

FIGURE 13.3: Outline of a program with one rea tive omponent,


a button. (Other types of rea tive omponents are similar. Programs
with more than one rea tive omponent are dis ussed later in this hap-
ter.)
18 CHAPTER 13. JAVA SWING (OPTIONAL)

UML diagram to be supplied


FIGURE 13.4: A UML lass diagram for a program with a Button.

a tually implement the interfa e methods. This is an example where


it makes sense to group the methods of a lass| onstru tors, a es-
sors, et ., in luding those methods that provide the implementation
UML stereotype for an interfa e. That group of methods an be separated by a UML
stereotype|a des riptive word en losed in guillemets ().
Let's give a simple example. We'll esh out the outline of Fig-
ure 13.3. The text in the button will be a stringi ed integer, and ea h
li k of the button will in rement the integer:

1 import javax.swing.*;
2 import java.awt.*;
3 import java.awt.event.*;
4
5 publi lass ButtonInt extends JFrame
6 implements A tionListener {
7
8 JButton intButton;
9 int ount = 0; // our ounter
10
11 publi ButtonInt () {
12 super("Button Counter");
13 intButton = new JButton("" + ount);
14
15 intButton.addA tionListener(this);
16
17 Container p = getContentPane();
18 p.setLayout(new FlowLayout());
19 p.add(intButton);
20
21 pa k();
22 setVisible(true);
23 }
24
25 publi void a tionPerformed (A tionEvent e) {
26 ount++;
27 intButton.setText("" + ount);
28 }
29 }

Whenever the JButton intButton is pressed, the a tionPerformed


method is alled. It in rements ount and hanges the label of intButton.
The JFrame is automati ally redisplayed to re e t the hange in its
ontents. The output after the button has been pressed three times is:
13.3. THE JAVA AWT EVENT MODEL 19
UML diagram to be supplied
FIGURE 13.5: A UML lass diagram for ClosableJFrame.

This same idea works for other omponents, but the details may
vary. For example, some omponents are registered as ItemListeners
instead of A tionListeners, using the method addItemListener in-
stead of addA tionListener. Another ompli ating fa tor is that
a program may ontain more than one rea tive omponent, and
a tionPerformed needs to know whi h one to rea t to. We will address
these issues shortly.

13.3.1 Closing the Window

You may have noti ed (espe ially if you've been doing the Qui k Ex-
er ises) that when running the TwoButtons program not all of the
standard buttons on the frame work. The minimize and maximize but-
tons work ne, but the \ lose window" button does not. It loses the
window, but it doesn't terminate the program. The reason for this is
that the Java implementation of JFrame is apable of generating various
WindowEvents su h as the losing of the window, the i oni ation of WindowEvents
the window, et . (See Table 13.6.). Some of these events ause a hange
in the appearan e of the window { su h as i oni ation/dei oni ation.
But others ause no spe ial hange in the window's appearan e, and
have no other asso iated a tion { it is ne essary for the programmer to
provide listeners if there is to be any a tion taken.
If we want our program to listen for the window losing event,
we must implement the WindowListener interfa e, and its seven re- WindowListener
quired methods. These are summarized in Table 13.7. Of ourse, we
ould do this dire tly in the lasses themselves. But writing ode for
losing a window is done so often that we usually de ne a new lass,
say ClosableJFrame, that extends Java's JFrame. Then instead of
TwoButtons extending JFrame, we have it extend ClosableJFrame.
20 CHAPTER 13. JAVA SWING (OPTIONAL)

Name Des ription


stati int WINDOW ACTIVATED The window has been made the user's a tive
window.
stati int WINDOW CLOSED The window has been losed.
stati int WINDOW CLOSING The window is being losed.
stati int WINDOW DEACTIVATED The window is no longer the user's a tive win-
dow.
stati int WINDOW DEICONIFIED The window has been dei oni ed.
stati int WINDOW ICONIFIED The window has been minimized.
stati int WINDOW OPENED The window has been made visible for the
rst time.

TABLE 13.6: Some onstants of the WindowEvent lass.

Method Purpose
void windowOpened (WindowEvent e) alled when a window is opened
void windowClosing (WindowEvent e) alled when a window is being losed
void windowClosed (WindowEvent e) alled when a window has been
losed
void windowI onified (WindowEvent e) alled when a window is i oni ed
void windowDei onified (WindowEvent e) alled when a window is dei oni ed
void windowA tivated (WindowEvent e) alled when a window is a tivated
void windowDea tivated (WindowEvent e) alled when a window is dea tivated

TABLE 13.7: The WindowListener interfa e. Window events are gen-


erated by mouse a ions on a Window obje t.

The a tion that we usually want to de ne is windowClosing, within


whi h we just terminate the program. ClosableJFrame is shown in
Figure 13.6.
The UML diagram for ClosableJFrame and window events (Fig-
ure 13.5) losely resembles that of Figure 13.4 where we diagramed
Button a tion events. However, this time the sour e of the event is not
a reated omponent, but the Window an estor of JFrame.
Noti e in line 4 that the new lass extends JFrame and imple-
ments the WindowListener interfa e. The main onstru tor in lines 10
through 13 invokes the JFrame's onstru tor, and then registers \this"
instan e as a listener for window events. In lines 15 through 18 we
implement the method that will be alled when the user attempts to
lose the window; this method alls dispose(), whi h leans up the
resour es used by the JFrame, and then terminates the program via a
all to System.exit(0). The remaining WindowListeners are de ned
as do-nothing methods in lines 19 through 24.
13.3. THE JAVA AWT EVENT MODEL 21

1 import javax.swing.*;
2 import java.awt.*;
3 import java.awt.event.*;
4
5 publi lass ClosableJFrame extends JFrame implements WindowListener {
6
7 publi ClosableJFrame () {
8 this("");
9 }
10
11 publi ClosableJFrame (String title) {
12 super(title);
13 addWindowListener(this);
14 }
15
16 publi void windowClosing (WindowEvent e) {
17 dispose();
18 System.exit(0);
19 }
20 publi void windowA tivated (WindowEvent e) {}
21 publi void windowClosed (WindowEvent e) {}
22 publi void windowOpened (WindowEvent e) {}
23 publi void windowDea tivated (WindowEvent e) {}
24 publi void windowDei onified (WindowEvent e) {}
25 publi void windowI onified (WindowEvent e) {}
26
27 }

FIGURE 13.6: The ClosableJFrame lass.

Change the version of TwoButton that inherited from JFrame


(page 15) so that it inherits from CloseableJFrame instead.
Qui k Exer ise 13.4
22 CHAPTER 13. JAVA SWING (OPTIONAL)

Name Des ription


stati int CENTER Indi ates that the label should be entered.
stati int LEFT Indi ates that the label should be left justi-
ed.
stati int RIGHT Indi ates that the label should be right justi-
ed.
JLabel () Constru ts a new label.
JLabel (String s) Constru ts a new label with s as the text, left
justi ed.
JLabel (String s, int align) Constru ts a new label with s as the text,
with the spe i ed alignment.
JLabel (I on i) Constru ts a new label ontaining i on i.
String getText () Get the text that for this label.
setText (String t) Set the text for this label to t.

TABLE 13.8: Some onstants and methods of the JLabel lass. Other
methods are inherited from JComponent.

13.4 Other Simple Components

For our next example, we need to introdu e two new omponents:


JLabel and JTextField.
A JLabel omponent ontains some text that an be set using
either the onstru tor, or the method setText (String t). It is the
simplest of all omponents and is used merely to display output; it
is not a rea tive omponent. Its methods are given in Table 13.8.
The one new method is the third onstru tor, with the align argu-
ment: this argument | one of the symboli onstants JLabel.CENTER,
JLabel.LEFT, and JLabel.RIGHT | says how to justify the text within
the label. If the label is set at its preferred size, it will be just large
enough to t the text and the alignment will be irrelevant. However,
this will matter if the label ends up being larger than the text itself
(whi h an happen, as we will see a little later).
More important is the JTextField, whi h allows users to type text
input to programs (as we have done with the CSLib lass InputBox).
A JTextField is a box into whi h a user an type text. It is ed-
itable in simple ways (ba kspa e, delete, et .). The text an be re-
trieved using String getText (), and an be set by the progam using
setText (String s). Its methods are shown in Table 13.9.
Like the JButton, the JLabel and JTextField have preferred
sizes that are just large enough to a ommodate them. Ea h of these
GUI omponents are sub lasses of the JComponent lass; the important
inherited methods are summarized in Table 13.2.
13.5. A TEMPERATURE CONVERSION GUI 23

Name Des ription


JTextField () Constru ts a new text eld.
JTextField (int ) Constru ts a new empty text eld with
olumns.
JTextField (String s) Constru ts a new text eld with s as the text.
void addA tionListener Makes l a listener for a tion events from this
(A tionListener l) text eld.
void setColumns (int ) Set the number of olumns to .
String getText () Get the text that is in this text eld.
String setText (String s) Set the text in this text eld to s.

TABLE 13.9: Some methods of the JTextField lass. Other methods


are inherited from JComponent. addA tionListener is explained in
Se tion 13.3.

13.5 A Temperature Conversion GUI

Our next example shows the use of labels and text elds. Re all the
temperature onversion program from Se tion ?? on page ??. We'll
rewrite that program to take its input from a JTextField, and to
produ e its output in a JLabel, with ea h omponent pla ed in the
JFrame.
Our program, alled TempConversion, reates a JTextField in
whi h to enter a number; that number is interpreted as a number of
degrees on the Fahrenheit s ale, and its equivalent on the Centigrade
s ale is displayed. The program is shown in Figure 13.7, and a snapshot
of the program's output is shown in Figure 13.8.
The rst few lines are just as in the prototype in Figure 13.3.
We have the usual import statements, the extends ClosableJFrame
lause, the implements A tionListener lause, the onstru tor, and
the required method a tionPerformed.
Noti e how, in lines 10 and 11, we have de lared the obje ts tFahr
and lCent. The reason for the strange looking names is that we have
used a onvention for naming variables that refer to omponents, in
whi h the rst letter tells something about the nature of the omponent.
In these ases, the leading t tells us that tFahr refers to a text eld,
and the leading l tells us that lCent refers to a label. As with other
naming onventions, this is merely a suggestion that sometimes helps
us remember what a variable means. You might imagine that, without
some sort of naming onvention, we might use the name labelCent on
one day, outputCent on another, and entMessage on yet another. In
graphi al programs, variables that refer to omponents (su h as lCent
and tFahr) are usually instan e variables, so that they an be initialized
by the onstru tor, and a essed by listeners and other methods.
24 CHAPTER 13. JAVA SWING (OPTIONAL)

1 import javax.swing.*;
2 import java.awt.*;
3 import java.awt.event.*;
4
5 publi lass Temperature extends ClosableJFrame
6 implements A tionListener {
7 // Convert from Fahrenheit to Centigrade
8 // Author: Jennifer Mi kunas, August 23, 2002
9
10 JTextField tFahr;
11 JLabel lPrompt, lCent;
12
13 publi Temperature () {
14
15 // Set the title and the layout manager
16 super("Temperature Conversion");
17 Container p = getContentPane();
18 p.setLayout(new FlowLayout());
19
20 // Create the TextField and the Label
21 tFahr = new JTextField(10);
22 lCent = new JLabel("I'll tell you what that is in degrees C");
23 lPrompt = new JLabel("Please type the temperature (deg F): ");
24
25 // Lay out the three Components
26 p.add(lPrompt);
27 p.add(tFahr);
28 p.add(lCent);
29 pa k();
30 setVisible(true);
31
32 // Register the Component Listener
33 tFahr.addA tionListener(this);
34 }
35
36 // Respond to A tion Event: typing in the tFahr TextField
37 publi void a tionPerformed (A tionEvent e) {
38 double fahr=0.0,
39 ent=0.0;
40 fahr = Integer.parseInt(tFahr.getText());
41 ent = 5.0 * (fahr - 32) / 9.0;
42 lCent.setText(fahr + " deg F is " + ent + " deg C");
43 pa k();
44 }
45 }

FIGURE 13.7: A GUI Temperature Conversion Program


13.5. A TEMPERATURE CONVERSION GUI 25

FIGURE 13.8: Output from the temperature onversion program.

Other familiar parts of the program are in lines 15 through 28,


where the frame details are handled (setting the title via the super
onstru tor, setting the layout manager, pa king the frame, and making
the frame visible), and where the JTextField and two JLabels are
reated and added to the frame; these an be seen in Figure 13.8. (As
we mentioned before, JTextFields are used to allow users to enter
text. In doing so, users an employ the standard methods of editing
with whi h anyone who has lled in a form on a web page is familiar:
sele ting text by li king and dragging, repla ing text by sele ting it
and typing the new text, deleting hara ters using the ba kspa e and
delete keys, and so on. All these a tions are handled by the JTextField
lass.)
The remaining lines of the program relate to the a tions of read-
ing from the JTextField and displaying the onverted temperature,
and mirror the three steps outlined for a JButton. Starting on line 37,
the program de nes the method a tionPerformed, to be alled when
the user presses the Enter key. That method gets the String that was
entered, and alls method Integer.parseInt (String s) to onvert
it to an int. The method then performs the onversion to Centigrade,
and nally hanges the label lCent to a new string. Be ause lCent has
already been added to the frame, this new label value shows up imme-
diately. The purpose of the pa k all in line 43 is to resize the frame
26 CHAPTER 13. JAVA SWING (OPTIONAL)

Name Des ription


Integer (int v) Constru ts an Integer with value v.
Integer (String s) Constru ts an Integer with value given by
the string s. It is an error if s has any non-
integer hara ters, in luding blanks.
int ompareTo (Integer b) Compare this Integer to b, returning -1, 0,
or +1 for less than, equal to, or greater than
result.
int intValue () Return the int value of this Integer.
stati int parseInt (String s) Parse s, returning the int it represents.
Equivalent to new Integer(s).intValue().
String toString () Stringi es this Integer.

TABLE 13.10: Some methods of the Integer lass.

to just the right size to a ommodate the Centigrade temperature.


Integer is another of Java's prede ned lasses, meant primarily
for working with integers as obje ts rather than as primitive ints. It
essentially \wraps" an int in a lass stru ture, so that it an be treated
as an obje t. The Integer lass has a number of instan e methods and
stati methods, and is summarized in Table 13.10. Here we have used
just the lass method parseInt.

Run the Temperature program. Try out a number of a -


tions with the program. Does everything work as you would
expe t?
Qui k Exer ise 13.5

13.6 Multiple Rea tive Components

To show how to deal with multiple rea tive omponents we'll extend
the Fahrenheit to Centigrade temperature onversion program. This
time, we will write the program so that it an overt temperatures
in either dire tion. Instead of one input text eld, we will have two.
Depending on whi h one the user utilizes for input, the program will
ompute the appropriate onverted temperature and display it in the
other text eld (using setText|see Table 13.9). The program is
1 import javax.swing.*;
2 import java.awt.*;
13.6. MULTIPLE REACTIVE COMPONENTS 27

3 import java.awt.event.*;
4
5 publi lass Temperature extends ClosableJFrame
6 implements A tionListener {
7
8 // Convert temperature from/to Fahrenheit/Centigrade
9 // Author: Peter Baranowi z, September 10, 2000
10
11 JTextField tFahr = new JTextField(9),
12 tCent = new JTextField(9);
13
14 publi Temperature () {
15 super("Two Way Conversion");
16
17 // Lay out the Components.
18 Container p = getContentPane();
19 p.setLayout(new FlowLayout());
20 p.add(new JLabel("Fahrenheit"));
21 p.add(tFahr);
22 p.add(new JLabel("Centigrade"));
23 p.add(tCent);
24 pa k();
25 setVisible(true);
26
27 // Register Component Listeners
28 tFahr.addA tionListener(this);
29 tCent.addA tionListener(this);
30 }
31
32 publi void a tionPerformed (A tionEvent e) {
33 // Respond to A tion Events:
34 // 1. tFahr TextField
35 // 2. tCent TextField
36 double fahr, ent;
37
38 if (e.getSour e()==tFahr) {
39 fahr = Double.parseDouble(tFahr.getText());
40 ent = 5.0 * (fahr - 32.0) / 9.0;
41 tCent.setText( ent + "");
42 }
43 else {
44 ent = Double.parseDouble(tCent.getText());
45 fahr = 9.0 * ent / 5.0 + 32.0;
46 tFahr.setText(fahr + "");
47 }
48 }
49 }
28 CHAPTER 13. JAVA SWING (OPTIONAL)

In lines 11 and 12, we de lared the two JTextFields that we


use. We use the same me hanism as before for reating a JTextField,
ex ept that this time we use an initializer in the de laration; this is
in onsequential and is simply a matter of taste. In the Temperature
onstru tor, we arrange for a ow layout manager, set up the window
with the two labeled JTextFields (and aÆliated JLabels), and register
them both by alling addA tionListener.
Now we must handle two possible A tionEvents: data input (that
is, the user typing the Enter key) in the tFahr JTextField and data
input in the tCent JTextField. But there an be only one de ni-
tion of the method a tionPerformed, whi h will be invoked for ei-
ther a tion. To distinguish the two events, we use the argument e of
a tionPerformed The method all e.getSour e() in line 38 identi-
es the parti ular omponent in whi h the event o urred. Thus, we
an tell if the user typed the Enter key in the tFahr eld by the test
e.getSour e() == tFahr; in that ase, we ll in tCent. Otherwise,
the user entered a number in tCent and we need to ll in tFahr. The
only methods of interest in lass A tionEvent are those inherited from
lass EventObje t, summarized in Table 13.11.
Another extension to this program will permit the user to type a
de imal number in the JTextField, so we need to re eive a double in-
stead of an int. Re all that the Integer lass has a method parseInt;
the Double lass has a similar method, alled parseDouble. The
Double lass is summarized in Table 13.12. Finally, the appropri-
ate onversion is omputed in line 40, and the other JTextField is
lled out in line 41. Thus, JTextFields an be used both to re-
eive input (as in tFahr.getText()) and to display output (as in
tCent.setText( ent + "")). Noti e that, in line 41, we did not
13.6. MULTIPLE REACTIVE COMPONENTS 29

Name Des ription


publi Obje t getSour e () Return the obje t on whi h the event initially
o urred.
String toString () Stringify the event obje t.

TABLE 13.11: Methods of the EventObje t lass. A tionEvent is a


sub lass of EventObje t.
Name Des ription
Double (double v) Constru ts an Double with value v.
Double (String s) Constru ts an Double with value given by the
string s. It is an error if s has any non-
de imal hara ters, in luding blanks.
int ompareTo (Double b) Compare this Double to b, returning -1, 0,
or +1 for less than, equal to, or greater than
result.
double doubleValue () Return the double value of this Double.
double parseDouble (String s) Parse s, returning the double it
represents. Equivalent to new
Double(s).doubleValue().
String toString () Stringi es this Double.

TABLE 13.12: Some methods of the Double lass.

write tCent.setText( ent) be ause setText requires a String, not


a double. The ode in the else alternative is the ounterpart of that
in the then alternative.

Try hanging line 41 in the Temperature program to


tCent.setText( ent);. What happens?
Qui k Exer ise 13.6

13.6.1 Che k boxes and radio buttons

There are many omponent lasses in Swing. The JChe kBox and the
similar JRadioButton are simple rea tive omponents that are very
mu h like buttons, ex ept in one way: instead of generating \a tion
events," they generate \item events." The on ept is the same, but the
details are di erent.
30 CHAPTER 13. JAVA SWING (OPTIONAL)

A he k box is a simple li kable on/o box. A JChe kBox always


has a label, and the user li ks on it to \sele t" or \desele t" it. The
general form for de laring and adding a JChe kBox is
JChe kBox hoi e = new JChe kBox("label");
...
p.add( hoi e);

JChe kBoxes typi ally are used to sele t one or more items. For exam-
ple, if you were ordering a ar, you might he k \power brakes" and
\power steering" but omit \air onditioning."
JChe kBox powerBrakes = new JChe kBox("Power Brakes");
JChe kBox powerSteering = new JChe kBox("Power Steering");
JChe kBox airConditioning = new JChe kBox("Air Conditioning");
...
p.add(powerBrakes);
p.add(powerSteering);
p.add(airConditioning);

This would look like

A JChe kBox is a rea tive omponent, like a JTextField: the


program may need to rea t when the user li ks on it. However, a
JChe kBox is registered in a slightly di erent way than a JTextField.
Spe i ally, the program is de lared with implements ItemListener
(instead of A tionListener), the JChe kBox is registered by alling
addItemListener (instead of addA tionListener), and the event is
itemStateChanged handled by method itemStateChanged (instead of a tionPerformed).
13.6. MULTIPLE REACTIVE COMPONENTS 31
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

:::

publi lass lassname extends JFrame implements ItemListener f


:::

JChe kBox boxname;


:::

publi lassname () f
:::

boxname = new JChe kBox(" he kbox label");


:::

Container p = getContentPane();
p.add( boxname);
:::

boxname.addItemListener(this);
:::

:::

publi void itemStateChanged (ItemEvent e) f


::: what to do when boxname is li ked :::

g
g

FIGURE 13.9: Outline of a program with one rea tive omponent, a


he kbox.

This is summarized in Figure 13.9. Just as a tionPerformed


has an argument of type A tionEvent, itemStateChanged has
an argument of type ItemEvent that an be used to distin-
guish among di erent JChe kBox omponents. That is, within
itemStateChanged (ItemEvent e), we an use e.getSour e() to tell
whi h item event triggered the state hange, just as we distinguished
among multiple JTextField A tionEvents in the temperature onver-
sion program. The lasses JChe kBox and ItemEvent are summarized
in Tables 13.13 and 13.14, and the ItemListener interfa e is summa-
rized in Table 13.15.
Often, we want only one of a group of he kboxes to be sele ted at
any one time; su h groups of are alled radio buttons (be ause they be- radio buttons
have like the pushbuttons on a radio). In Swing, we use JRadioButton
for the individual radio buttons, and ButtonGroup to represent the
32 CHAPTER 13. JAVA SWING (OPTIONAL)

Name Des ription


JChe kBox () Create a new he k box with no label.
JChe kBox (String l) Create a new he k box with label l.
JChe kBox (String l, boolean Create a new he k box with label l; sele ted
state) if state == true.
JChe kBox (I on i) Create a new he k box with label l.
JChe kBox (I on i, boolean Create a new he k box with label l; sele ted
state) if state == true.
void addItemListener Makes l a listener for item events from this
(ItemListener l) he k box.
String getLabel () Get the label of this he k box.
boolean isSele ted () Get the state of this he k box.
void setLabel (String l) Set the label of this he k box.
void setSele ted (boolean Set the state of this he k box.
state)

TABLE 13.13: Some methods of the JChe kBox lass.

Name Des ription


stati int DESELECTED Indi ates that the item was desele ted.
stati int SELECTED Indi ates that the item was sele ted.
int getStateChange () Return the type of state hange.

TABLE 13.14: Some onstants and methods of the ItemEvent lass.


(Other methods are inherited from EventObje t.)

Method Purpose
void itemStateChanged (ItemEvent e) alled when any item event o urs

TABLE 13.15: The ItemListener interfa e. Item events are generated


by he kboxes.
13.6. MULTIPLE REACTIVE COMPONENTS 33

Name Des ription


JRadioButton () Create a new radio button.
void addItemListener Makes l a listener for item events from this
(ItemListener l) radio button.
String getLabel () Get the label of this radio button.
boolean isSele ted () Get the state of this radio button.
void setLabel (String l) Set the label of this radio button.
void setSele ted (boolean Set the state of this radio button.
state)

TABLE 13.16: Some methods of the JRadioButton lass.

entire group.2 When we reate a JRadioButton, we an tell Java to


in lude it as part of a ButtonGroup; we must also tell whether the
JRadioButton should be sele ted (true) or not (false). For exam-
ple, when ordering a ar, you might hoose \hardtop" or \ onvertible,"
but not both. To add RadioButtons for these hoi es, while making
\hardtop" the default sele tion, we would write
ButtonGroup bodyStyle = new ButtonGroup();
JRadioButton hardtop = new JRadioButton("Hardtop", true);
JRadioButton onvertible = new JRadioButton("Convertible", false);
bodyStyle.add(hardtop);
bodyStyle.add( onvertible);
...
p.add(hardtop);
p.add( onvertible);

If the user sele ts one JRadioButton in a ButtonGroup, the previously


sele ted JRadioButton will be unsele ted. Java provides a method for
nding out whi h JRadioButton in a group is sele ted:
JRadioButton ButtonGroup.getSele tion()
The lasses JRadioButton and ButtonGroup are summarized in Ta-
bles 13.16 and 13.17, respe tively.
Let's rewrite the body mass program from Exer ise ?? on page ??.
This time, we will have a JTextField for height, a JTextField for
weight, and radio buttons to sele t male or female. The omplete
program is
1 import javax.swing.*;
2 import java.awt.*;
3 import java.awt.event.*;
4

2 Note that this is ButtonGroup, not JButtonGroup.


34 CHAPTER 13. JAVA SWING (OPTIONAL)

Name Des ription


ButtonGroup () Create a new button group.
void add (JRadioButton b) Add b to this button group.
void remove (JRadioButton b) Remove b from this button group.
JRadioButton getSele tion () Return a referen e to the urrently sele ted
button in this group.
void setSele ted (JRadioButton Set box as the sele ted he k box in this but-
box, boolean b) ton group (if b is true).
boolean isSele ted Test if box is the sele ted radio button.
(JRadioButton box)
int getButtonCount () Returns the number of buttons in this group.

TABLE 13.17: Some methods of the ButtonGroup lass.

5 publi lass BodyMass extends ClosableJFrame


6 implements ItemListener, A tionListener {
7
8 // Determine Body-Mass-Index and Obesity
9 // Author: Deborah Mi kunas, O tober 13, 2002
10
11 // De lare Components
12 JTextField tHeight, tWeight;
13 JLabel lIndex, lHigh;
14 ButtonGroup gender;
15 JRadioButton maleRadio, femaleRadio;
16
17 publi BodyMass () {
18 super("Body Mass Program");
19
20 // Allo ate omponents.
21 tHeight = new JTextField(5);
22 tWeight = new JTextField(5);
23 lIndex = new JLabel("What is your body-mass-index? ");
24 lHigh = new JLabel("Is this onsidered high or not?");
25 gender = new ButtonGroup();
26 maleRadio = new JRadioButton("Male", true);
27 femaleRadio = new JRadioButton("Female", false);
28 gender.add(maleRadio);
29 gender.add(femaleRadio);
30
31 // Arrange Components
32 Container p = getContentPane();
33 p.setLayout(new FlowLayout());
34 p.add(maleRadio);
35 p.add(femaleRadio);
36 p.add(new JLabel("Height (in meters):"));
37 p.add(tHeight);
13.6. MULTIPLE REACTIVE COMPONENTS 35

38 p.add(new JLabel("Weight (in kilograms):"));


39 p.add(tWeight);
40 p.add(lIndex);
41 p.add(lHigh);
42
43 setSize(250,200);
44 setVisible(true);
45
46 // Register Component Listeners
47 tHeight.addA tionListener(this);
48 tWeight.addA tionListener(this);
49 maleRadio.addItemListener(this);
50 femaleRadio.addItemListener(this);
51 }
52
53 publi void itemStateChanged (ItemEvent e) {
54 // Respond to Item Events:
55 // 1. femaleRadio radio button
56 // 2. maleRadio radio button
57 ompute();
58 }
59
60 publi void a tionPerformed (A tionEvent e) {
61 // Respond to A tion Events:
62 // 1. tHeight TextField
63 // 2. tWeight TextField
64 ompute();
65 }
66
67 private void ompute () {
68 double height = Double.parseDouble(tHeight.getText());
69 double weight = Double.parseDouble(tWeight.getText());
70 double bodyMassIndex = weight / (height * height);
71 boolean female = (gender.getSele tion() == femaleRadio);
72
73 lIndex.setText("Your body-mass-index is " + bodyMassIndex);
74 if ((bodyMassIndex > 27.8) ||
75 female && (bodyMassIndex > 27.3))
76 lHigh.setText("This is onsidered high.");
77 else
78 lHigh.setText("This is not onsidered high.");
79 }
80 }

Sin e this program ontains both JTextFields and


JRadioButtons, it de lares itself to implement both the
A tionListener and ItemListener interfa es (lines 5 and 6).
Noti e how the two JRadioButtons are added to the gender
ButtonGroup (lines 26 through 29) with the maleChe k radio button
36 CHAPTER 13. JAVA SWING (OPTIONAL)

initially sele ted. Our ode registers \this" program as the listener for
all four of the omponents (lines 47 through 50).
Within the itemStateChanged method (lines 53 through 58), we
ould he k to see whi h JRadioButton triggered the ItemEvent in the
same way that we he ked for JTextField events. However, the only
thing that we really need to do is all the private method ompute,
where all of the real work is done. Likewise, in the a tionPerformed
method (lines 60 through 65), we just all the ompute method.
Within ompute, we rst read the input from both the tHeight
and the tWeight JTextField, and ompute bodyMassIndex (lines 68
through 69). Then we determine whi h of the gender RadioButtons is
sele ted in line 71. Note that line 71 is just a leaner way of writing
if (gender.getSele tion() == femaleChe k)
female = true;
else
female = false;

Finally, we display the results in two JLabel Components in


lines 73 through 78. On e the program is under way, the s reen might
appear as shown in Figure 13.10. Noti e that rather than using pa k(),
we set the Frame size expli itly to 250  200 pixels.
When we rst start up the program, we need to display something
in the two JLabels lIndex and lHigh. When they are de lared and
reated, we spe ify that they should initially display some meaningful
messages; more pre isely, \What is your body-mass-index?" and \Is
this high or not?" These labels are then hanged, in ompute, to show
the results.

13.7 The Swing Component Hierar hy

THIS SECTION NEEDS TO BE WRITTEN.

13.8 Designing the S reen Layout

In this se tion, we will introdu e the s reen layout apabilities of Java


by revisiting the BodyMass program from Se tion 13.18 (page 35). We
have not yet dis ussed alternative ways of arranging omponents as
they are added to a ontainer. We have been areful to hoose a size
for ea h frame so that it looks ne, but if the user resizes the frame, the
appearan e may not be pleasing. For example, if you run the BodyMass
program on page 35 and drag on the right side to widen the frame, you
might get something resembling Figure 13.11.
This o urs be ause, when we add omponents to the frame, they
are laid out left to right as room permits and pla ed on a new line only
13.8. DESIGNING THE SCREEN LAYOUT 37

FIGURE 13.10: Typi al output from the BodyMass program.

What would the output of the Body Mass program look like
if we had not expli itly set the frame size to 250  200? What
would it have looked like if instead we had done a pa k()?
Qui k Exer ise 13.7
38 CHAPTER 13. JAVA SWING (OPTIONAL)

In the Body Mass program, what happens if you enter zero


for the height (or just li k on a radio button with blanks
in the height eld)? How might you hange the program to
have better behavior in su h ir umstan es?
Qui k Exer ise 13.8

FIGURE 13.11: Poor layout for the body mass program.


13.8. DESIGNING THE SCREEN LAYOUT 39

when required. This is a onsequen e of the Layout Manager, whi h Layout Manager
governs how omponents are arranged when they are added to a frame.
In our programs so far in this hapter, we used the FlowLayout layout
manager.
The Java API de nes several layout manager lasses. To hange
the layout manager used by a graphi al frame, send the message
setLayout( layout-manager-obje t);
to the frame. In the remaining programs of this hapter, we will use
three layout managers:
FlowLayout. If the frame's layout manager is set to be an obje t of
this lass,
setLayout(new FlowLayout());

then the frame will arrange the omponents a ording to the order
in whi h they were added (by add), going left to right and top to
bottom, as we have seen.
BorderLayout. When this type of layout is used,
setLayout(new BorderLayout());

the frame is divided into north, south, east, west, and enter areas,
as shown in Figure 13.12. Components are added to the frame
with a spe ial two-argument add method. For example,
add(new JLabel("The Title"), BorderLayout.NORTH);

adds The Title to the top of the window, entered. It is an


error to add two omponents to the same position in the win-
dow. BorderLayout is the default layout manager for JFrames.
(This explains why our programs don't work if the layout man-
ager is not hanged to FlowLayout. In BorderLayout, the all
add( omponent) has an unpredi table e e t.)
GridLayout. With a GridLayout obje t as its layout manager, the
frame will arrange itself into a grid of xed size and pla e obje ts
into the grid in the order in whi h they were added (by add), going
left to right and top to bottom. For example,
setLayout(new GridLayout(3, 5));

divides the frame into a grid with three rows and ve olumns;
it is an error to add more than 15 omponents, but if fewer are
added the leftover pla es in the grid will be left empty. All ells
of the grid have the same dimensions.
40 CHAPTER 13. JAVA SWING (OPTIONAL)

FIGURE 13.12: The BorderLayout manager.

For example, using GridLayout, one might arrange a list of labels


in the frame using these lines:
p.setLayout(new GridLayout(3, 2));
p.add(new JLabel("Roger Ebert"));
p.add(new JLabel("Two thumbs up!"));
p.add(new JLabel("Janet Maslin"));
p.add(new JLabel("Hated it!"));
p.add(new JLabel("Rex Reed"));
p.add(new JLabel("I an't de ide."));

By using GridLayout, the labels will always line up in two olumns,


no matter how the frame is resized. (Noti e that this is a ase where
the preferred sizes of the labels may be ignored, sin e ea h label will
ne essarily o upy the same amount of spa e.)
Used alone, the layout managers rarely give good results. Usually,
di erent parts of the frame need to be organized di erently. To a hieve
ontainers this, you an use ontainers. Containers are omponents that ontain
other omponents. As we have seen, the ontent pane of a JFrame is a
ontainer. If you want to reate your own ontainer obje ts, you an do
so by reating an obje t of lass JPanel. Being a ontainer, a JPanel
has its own layout manager, and omponents are added to it just as
they are added to the ontent pane of a JFrame. Then, the JPanel
is treated as a single omponent that is added to another ontainer,
a ording to that ontainer's layout manager. Therefore, it is typi al
to see ode like this to build a GUI:
JPanel p1 = new JPanel();
13.8. DESIGNING THE SCREEN LAYOUT 41

p1.setLayout(new GridLayout(2, 1));


p1.add( omponent1 );
p1.add( omponent2 );
JPanel p2 = new JPanel();
p2.setLayout(: : :);
p2.add( omponent3 );
...
setLayout(new BorderLayout());
p.add(p1, BorderLayout.NORTH);
p.add(p2, BorderLayout.SOUTH);
Even more omplex arrangements an be spe i ed by pla ing JPanels
inside other JPanels. (and by using some of the more sophisti ated
layout managers provided in Swing, whi h we have not overed). In-
identally, the default layout manager for JPanels is FlowLayout (not
BorderLayout, as it is for JFrames).
Now we rewrite the BodyMass program from Se tion 13.18. We
will improve the layout of the program so that the male/female radio
buttons will both be on line 1, the tHeight JLabel and orresponding
JTextField will be on line 2, the tWeight JLabel and orresponding
JTextField will be on line 3, the \What is your body-mass-index?"
JLabel will be on line 4, and the \Is this onsidered high or not?"
JLabel will be on line 5. The key point is that the arrangement will
remain this way no matter how the overall frame may be resized. Ea h
of these ve lines will be a separate omponent of a grid layout with
one olumn and ve rows. Moreover, ea h of the rst three will be
\en apsulated" in a JPanel using a ow layout. The new Body Mass
program follows:
1 import javax.swing.*;
2 import java.awt.*;
3 import java.awt.event.*;
4
5 publi lass BodyMass extends ClosableJFrame
6 implements ItemListener, A tionListener {
7
8 // Determine Body-Mass-Index and Obesity
9 // Author: Deborah Mi kunas, O tober 13, 1996
10
11 // De lare and allo ate Components
12 JTextField
13 tHeight = new JTextField(5),
14 tWeight = new JTextField(5);
15 JLabel
16 lIndex = new JLabel("What is your body-mass-index? "),
17 lHigh = new JLabel("Is this onsidered high or not?");
18 ButtonGroup
19 gender = new ButtonGroup();
20 JRadioButton
42 CHAPTER 13. JAVA SWING (OPTIONAL)

21 maleRadio = new JRadioButton("Male", true),


22 femaleRadio = new JRadioButton("Female", false);
23 JPanel
24 p1 = new JPanel(), // line 1
25 p2 = new JPanel(), // line 2
26 p3 = new JPanel(); // line 3
27
28 publi BodyMass () {
29 super("Body Mass Program");
30
31 gender.add(maleRadio);
32 gender.add(femaleRadio);
33
34 // Set Label properties
35 lIndex.setHorizontalAlignment(JLabel.CENTER);
36 lIndex.setFont(new Font("Helveti a", Font.PLAIN, 14));
37 lIndex.setForeground(Color.blue);
38
39 lHigh.setHorizontalAlignment(JLabel.CENTER);
40 lHigh.setFont(new Font("Courier", Font.BOLD, 18));
41 lHigh.setForeground(Color.red);
42
43 // Arrange Components
44 Container p = getContentPane();
45 p.setLayout(new GridLayout(5,1));
46 p1.add(maleRadio);
47 p1.add(femaleRadio);
48 p.add(p1);
49 p2.add(new JLabel("Height (in meters):"));
50 p2.add(tHeight);
51 p.add(p2);
52 p3.add(new JLabel("Weight (in kilograms):"));
53 p3.add(tWeight);
54 p.add(p3);
55 p.add(lIndex);
56 p.add(lHigh);
57
58 pa k();
59 setVisible(true);
60
61 // Register Component Listeners
62 tHeight.addA tionListener(this);
63 tWeight.addA tionListener(this);
64 maleRadio.addItemListener(this);
65 femaleRadio.addItemListener(this);
66 }
67
68 publi void itemStateChanged (ItemEvent e) {
69 // Respond to Item Events:
13.9. A CALENDAR PROGRAM 43

70 // 1. femaleRadio RadioButton
71 // 2. maleRadio RadioButton
72 ompute();
73 }
74
75 publi void a tionPerformed (A tionEvent e) {
76 // Respond to A tion Events:
77 // 1. tHeight TextField
78 // 2. tWeight TextField
79 ompute();
80 }
81
82 private void ompute () {
83 double height = new Double(tHeight.getText()).doubleValue();
84 double weight = new Double(tWeight.getText()).doubleValue();
85 double bodyMassIndex = weight / (height * height);
86 boolean female = femaleChe k.isSele ted();
87
88 lIndex.setText("Your body-mass-index is " + bodyMassIndex);
89 if ((bodyMassIndex > 27.8) ||
90 (female && (bodyMassIndex > 27.3)))
91 lHigh.setText("This is onsidered high.");
92 else
93 lHigh.setText("This is not onsidered high.");
94 pa k();
95 }
96 }

In lines 44 through 56, we add the appropriate omponents to


ea h of our new JPanels, and add ea h of those JPanels in turn to
the JFrame's ontent pane. Sin e those JPanels have not had layout
managers spe i ed for them, they ea h use the default FlowLayout
manager. The layout manager for the frame is set to a GridLayout
with one olumn and ve rows (line 45), so our ve omponents { three
panels and two labels { are added in the proper order. The startup
s reen is shown in Figure 13.13.

13.9 A Calendar Program

Our nal program in this hapter is one to display a monthly al-


endar, where the user an sele t the month and year. We use the
layout te hniques of this hapter, together with a new omponent|the
JS rollBar . The program will begin by displaying the present month, JS rollBar
but we will allow the user to sele t any month from January 1000 to
De ember 2199 by moving the s rollbar from side to side. When our
program runs, the s reen will look like Figure 13.14. (We moved the
display to show January 2000.)
44 CHAPTER 13. JAVA SWING (OPTIONAL)

FIGURE 13.13: The nal body mass program, resized.

Run the new BodyMass program with a variety of inputs, and


noti e how the frame resizes itself appropriately.
Qui k Exer ise 13.9
13.9. A CALENDAR PROGRAM 45

FIGURE 13.14: Output of the alendar program.

You annot tell by the gray s ale pi ture, but the \January 2000"
banner is red on a yellow ba kground, and the body of the alendar is
blue on gray. By examining the desired s reen appearan e, you may be
able to dedu e what kinds of JPanels and layouts we use. The names
that we give to the various omponents are
1. banner ontains the name of the month and the year.
2. sele t ontains the JS rollBar.
3. days is a JPanel ontaining the days of the week.
4. pBody is a JPanel ontaining the body of the alendar.
Before reading further, see if you an gure out our layout plan.
We use the BorderLayout manager (the one with "NORTH",
"SOUTH", "EAST", "WEST" and "CENTER" panes, shown in Figure 13.12).
For our alendar, the north strip will ontain the banner, the sele t,
and the days omponents; the enter portion will ontain the body
of the alendar. The remaining border positions will not be used, so
they will have zero size. The north strip is another JPanel with a
3  1 GridLayout; within this JPanel, the banner omponent will be
on line 1, the sele t omponent on line 2, and the days omponent
on line 3. The days omponent is yet another JPanel with a 1  7
GridLayout, ea h ell ontaining a JLabel telling the day of the week.
In the enter position we pla e a Panel that uses a 6  7 GridLayout,
putting a JLabel into ea h ell.
46 CHAPTER 13. JAVA SWING (OPTIONAL)

Why didn't we use a 4  1 grid layout for our alendar, with


the four rows ontaining the banner, the sele t, the days,
and the pBody omponents?
Qui k Exer ise 13.10

Method Purpose
void adjustmentValueChanged (AdjustmentEvent e) alled when any adjustment event
o urs

TABLE 13.18: The AdjustmentListener interfa e. Adjustment events


are generated by s rollbars.

Before we ontinue, it is ne essary to understand how the


JS rollBar omponent works. The leftmost position of the
JS rollBar orresponds to some integer value, and the rightmost to
a larger integer value. When instantiating a JS rollBar, the pro-
grammer must spe ify these extreme values, as well as the desired ini-
tial position of the \bubble," the desired dire tion of the s roll bar
(JS rollBar.HORIZONTAL or JS rollBar.VERTICAL), and the thi k-
ness of the bubble. During program exe ution, the user an ause the
JS rollBar's bubble to move toward one end or the other in three
ways:
1. Cli king on either \end button" auses the bubble to move one
\unit" in that dire tion.
2. Cli king in the area between an end button and the bubble auses
the bubble to move 10 units in that dire tion.
3. Cli king and dragging on the bubble an ause it to move to any
position.
These operations trigger events that the JS rollBar's
AdjustmentListener must interpret using the method
adjustmentValueChanged. The interfa e AdjustmentListener
is summarized in Table 13.18. Therefore, the JS rollBar is a omplex
but very powerful graphi al interfa e omponent that allows the
user to sele t an integer in a prede ned range. The methods of the
JS rollBar are summarized in Table 13.19.
We use the JS rollBar to sele t a month between January 1000
and De ember 2199. Sin e there are 12*1200 months in the range
of interest, we have our JS rollBar run through the values 0 to
14399, and we obtain the JS rollBar value in the variable tallyMonth.
13.9. A CALENDAR PROGRAM 47

Name Des ription


stati int HORIZONTAL Indi ates a horizontal s rollbar.
stati int VERTICAL Indi ates a verti al s rollbar.
JS rollBar () Create a new verti al s rollbar.
JS rollBar (int orient) Creates a new s roll bar with orient orien-
tation.
JS rollBar (int orient, int Create a new s roll bar with orient orienta-
value, int visible, int min, tion, value for its initial value, visible for
int max) the size of the bubble, and given min and max
values.
void addAdjustmentListener Make l a listener for this s rollbar's adjust-
(AdjustmentListener l) ment events.
int getBlo kIn rement () Return the blo k in rement value.
int getMaximum () Return the maximum value.
int getMinimum () Return the minimum value.
int getOrientation () Return the orientation.
int getUnitIn rement () Return the unit in rement.
int getValue () Return the urrent value of this s rollbar.
int getVisibleAmount () Return the size of the bubble.
void setBlo kIn rement (int i) Set the blo k in rement to i.
void setMaximum (int i) Set the maximum value to i.
void setMinimum (int i) Set the minimum value to i.
void setOrientation (int i) Set the orientation to i.
void setUnitIn rement (int i) Set the unit in rement to i.
void setValue (int i) Set the urrent value to i.
void setVisibleAmount (int i) Set the bubble size to i.
String toString () Stringify this s rollbar .

TABLE 13.19: Some onstants and methods of the JS rollBar lass.


48 CHAPTER 13. JAVA SWING (OPTIONAL)

Thus, tallyMonth=0 orresponds to month=1 and year=1000, while


tallyMonth=14399 orresponds to month=12 and year=2199. The
onversion from tallyMonth to month and year is quite easy:
year = tallyM onth=12
month = tallyM onth 12  year + 1
year = year + 1000

Here is the omplete ode for the Calendar program:


1 import javax.swing.*;
2 import java.awt.*;
3 import java.awt.event.*;
4 import java.util.*;
5
6 publi lass GUICalendar extends ClosableJFrame
7 implements AdjustmentListener {
8
9 // A Calendar, valid from 1/1/1000 to 12/31/2199
10 // Author: Mark J. Mi kunas, January 20, 2002
11
12 JLabel banner; // Month, year banner -- line 1
13 JS rollBar sele t; // S rollBar -- line 2
14 JPanel days, // days of week -- line 3
15 pHead, // ontains lines 1, 2, 3 -- pla e in "North" of frame
16 pBody; // ontains body -- pla ed in "Center" of frame
17
18 int tallyMonth; // in the range 0..14399
19
20 JLabel[℄[℄ lDate = new JLabel[6℄[7℄;
21
22
23 publi GUICalendar () {
24 super("Calendar");
25
26 // Find out today's date.
27 Calendar alendar = new GregorianCalendar();
28 int month = alendar.get(Calendar.MONTH);// 0 through 11 !!!
29 int year = alendar.get(Calendar.YEAR);
30
31 tallyMonth = (year-1000)*12 + month;
32
33 // Allo ate and lay out the omponents
34 banner = new JLabel();
35 banner.setHorizontalAlignment(JLabel.CENTER);
36 banner.setBa kground(Color.yellow);
37 banner.setFont(new Font("TimesRoman",Font.BOLD, 16));
38 banner.setForeground(Color.red);
39
13.9. A CALENDAR PROGRAM 49

40 sele t = new JS rollBar(


41 JS rollBar.HORIZONTAL, // orientation
42 tallyMonth, // initial value
43 1, // slider width
44 0, // minimum value
45 1200*12-1); // maximum value
46
47 days = new JPanel();
48 days.setLayout(new GridLayout(1,7));
49 for (int i = 0; i<7; i++) {
50 JPanel p = new JPanel();
51 p.add(new Label(MyDate.DAY_NAME[i℄, Label.CENTER));
52 days.add(p);
53 }
54
55 pHead = new JPanel();
56 pHead.setLayout(new GridLayout(3,1));
57 pHead.add(banner);
58 pHead.add(sele t);
59 pHead.add(days);
60
61 pBody = new JPanel();
62 pBody.setLayout(new GridLayout(6,7));
63 for (int i=0; i<6; i++)
64 for (int j=0; j<7; j++) {
65 lDate[i℄[j℄ = new JLabel("",JLabel.CENTER);
66 lDate[i℄[j℄.setForeground(Color.blue);
67 pBody.add(lDate[i℄[j℄);
68 }
69
70 Container p = getContentPane();
71 p.setLayout(new BorderLayout());
72 p.add(pHead, BorderLayout.NORTH);
73 p.add(pBody, BorderLayout.CENTER);
74
75 // Register this applet as the s rollbar listener.
76 sele t.addAdjustmentListener(this);
77 ompute();
78 pa k();
79 setVisible(true);
80 }
81
82 publi void ompute() {
83 // Given tallyMonth, set the banner appropriately
84 // and fill in the alendar body.
85
86 // Compute month/year from the s rollbar position
87 // and repaint the alendar body appropriately
88 int year = tallyMonth/12;
50 CHAPTER 13. JAVA SWING (OPTIONAL)

89 int month = tallyMonth - 12*year + 1;


90 year = year + 1000;
91
92 banner.setText (MyDate.MONTH_NAME[month℄ + ", " + year);
93
94 // Blank out the alendar
95 for (int i=0; i<7; i++)
96 for (int j=0; j<6; j++)
97 lDate[j℄[i℄.setText("");
98
99 // Day of the week for the day 1 of the month
100 int firstOfMonth = MyDate.dayOfWeek(month, 1, year);
101
102 // The first label to be filled is lDaye[0℄[firstOfMonth℄
103 int x = firstOfMonth;
104 int y = 0;
105
106 // Run through all days in the month
107 for (int i = 1;
108 i <= MyDate.lastDayOfMonth(month, year);
109 i++) {
110
111 lDate[y℄[x℄.setText(""+i);
112 x++;
113
114 // Is it time to move to the next line?
115 if (x==7) {
116 y++;
117 x = 0;
118 }
119 }
120 }
121
122 publi void adjustmentValueChanged (AdjustmentEvent e) {
123 // Handle the s rollbar events
124 tallyMonth = e.getValue();
125 ompute();
126 }
127 }

First, the onstru tor (lines 23 through 80) is where the work of
setting up the frame layout takes pla e. In the onstru tor, we
1. Determine the month, year for today's date (lines 26 through
29).
2. Compute tallyMonth (line 31) for the s rollbar.
3. Instantiate the banner JLabel, and set its alignment, font, and
foreground olor (lines 34 through 38).
13.9. A CALENDAR PROGRAM 51

Symboli Constant Purpose


stati int DAY OF MONTH Field number for day of the month.
stati int MONTH Field number for month.
stati int YEAR Field number for the year.
Method Purpose
int get (int field) Return the value for a spe i ed eld.

TABLE 13.20: A few onstants and methods of Java's Calendar lass.


.

4. Instantiate the sele t JS rollBar, setting its initial value to


tallyMonth (lines 40 through 45).
5. Lay out everything appropriately (lines 55 through 73).
6. Register AdjustmentListener(s) for the sele t JS rollBar
(line 75).
7. Call ompute() to initially set the banner JLabel and the alen-
dar body (line 76).
Within the onstru tor, we an ompute today's date by using
the lass GregorianCalendar in Java's java.util pa kage (lines 26
through 29). With the ex eption of the GregorianCalendar onstru -
tor, whi h returns today's date, the only methods and onstants that
we use are from GregorianCalendar's super lass, Calendar; these are
summarized in Table 13.20. We see that GregorianCalendar numbers
months from 0 through 11, whereas our Date lass uses 1 through 12,
so we must be aware of this when we write our ode.
The ompute method itself must
1. Constru t the month/year string from the value of tallyMonth
(lines 85 through 91).
2. Update the banner JLabel (line 91).
3. Set the 42 individual day labels to blank (lines 93 through 96).
4. Determine the rst day of the week to ll in, or equivalently, how
many labels to skip on the rst line (lines 99).
5. Pla e the numerals 1, 2, : : : last day of the month in su essive
labels (lines 101 through 118).
The reason why we en apsulate the ompute ode in a single method is
that it is alled from two pla es| rst from the Calendar's onstru tor,
and subsequently every time the s rollbar hanges.
52 CHAPTER 13. JAVA SWING (OPTIONAL)

The only event of interest is a tivity within the sele t s rollbar,


whi h is handled by the adjustmentValueChanged method:
122 publi void adjustmentValueChanged (AdjustmentEvent e) {
123 // Handle the s rollbar events
124 tallyMonth = e.getValue();
125 ompute();
126 }

For su h a JS rollBar event we must obtain the integer value for


the S rollBar's bubble (line 124) and then all ompute() to redraw
the alendar body.

13.10 Custom Drawing in Swing

In previous hapters we used the CSLib lass DrawingBox to draw pi -


tures and GIFs. Now we will see how to draw in a frame. The Java
API provides methods to draw lines, ir les, re tangles and text in a
frame and to in lude GIF and JPEG images, very mu h as we did with
the DrawingBox.
You don't a tually want to draw dire tly into a JFrame, or even
into its ontent pane. Instead, you should de ne a sub lass of JPanel
and add it to the JFrame in the usual way. In that lass, you should
de ne the method:
publi void paintComponent (Graphi s g)

The Graphi s obje t g is reated by the Java runtime system,


not by you, and it is used for drawing operations. The method
paintComponent will be alled by the Java runtime system whenever
the frame needs to be drawn, su h as when it is moved or resized or
dei oni ed or un overed.
The above is summarized in Figure 13.15. Note that the
rst statement in the paintComponent method should be to send
paintComponent to super.
Within your new lass, you an onsider the JPanel to be a grid,
with point (0; 0) at the upper left and some point with positive oordi-
nates (x; y), depending upon the size of the frame, at the lower right.
This is identi al to the DrawingBox oordinate system with whi h you
are already familiar. The Graphi s lass provides many of the same
drawing methods that are provided in the DrawingBox lass, plus many
more. A sele tion of these methods is given in Table 13.21.
As an example, we will redo the Clo k program from Se tion ??
on page ??. We'll simplify the old version of Clo k quite a bit, remov-
ing methods not used in this program (just to save spa e). And, as
re ommended above, we will make it a sub lass of JPanel. Here's the
new Clo k ode:
13.10. CUSTOM DRAWING IN SWING 53

import javax.swing.*;
import java.awt.*;

publi lass MyDrawing extends JPanel {


...
publi void paintComponent (Graphi s g) {
super.paintomponent(g);
...
g.drawLine(...);
...
g.drawImage(...);
...
}
...
}

FIGURE 13.15: Typi al Drawing Code.

Name Des ription


void learRe t (int x, int y, Clear re tangle of width w and height h with
int w, int h) upper-left orner at (x, y), by lling it with
ba kground olor
void drawLine (int x1, int y1, Draw line from (x1, y1) to (x2, y2)
int x2, int y2)
void drawOval (int x, int y, Draw oval that would pre isely t into the
int w, int h) re tangle given by these arguments (see
learRe t).
void drawPolygon (Polygon p) Draw polygon
void drawRe t (int x, int y, Draw outline of re tangle spe i ed by these
int w, int h) arguments (see learRe t)
void drawString (String s, int Draw s with its referen e point (bottom-left
x, int y) orner) at (x, y)
void fillOval (int x, int y, Like drawOval, but lls in urrent olor
int w, int h)
void fillPolygon (Polygon p) Draw polygon, lled with urrent olor
void fillRe t (int x, int y, Like drawRe t, but lls in urrent olor
int w, int h)
Color getColor () Get urrent olor
Font getFont () Get urrent font
FontMetri s getFontMetri s () Get font metri s of urrent font
void setColor (Color ) Set urrent olor to
void setFont (Font f) Get urrent font to f

TABLE 13.21: Some methods of the Graphi s lass.


54 CHAPTER 13. JAVA SWING (OPTIONAL)

1 import javax.swing.*;
2 import java.awt.*;
3
4 publi lass Clo k extends JPanel {
5
6 int hour,
7 minute;
8
9 publi Clo k () {
10 this(12,0);
11 }
12
13 publi Clo k (int hour, int minute) {
14 set(hour, minute);
15 }
16
17 publi void set (int hour, int minute) {
18 int totalMinutes = (hour * 60 + minute) % (12 * 60);
19 // totalMinutes is between -(12 * 60) and (12 * 60)
20 if (totalMinutes < 0) totalMinutes = totalMinutes + (12 * 60);
21 this.hour = totalMinutes / 60;
22 if (this.hour == 0) this.hour = 12;
23 this.minute = totalMinutes % 60;
24 }
25
26 publi int getHour () { return hour; }
27 publi int getMinute () { return minute; }
28
29 // Draw a lo k in this panel.
30 publi void paintComponent (Graphi s g) {
31
32 super.paintComponent(g);
33
34 int w = getWidth()-1,
35 h = getHeight()-1;
36 int x = w/2,
37 y = h/2; // enter at (x,y)
38 int r = Math.min(x, y); // radius
39
40 // Draw the lo k in bla k.
41 g.setColor(Color.bla k);
42 g.drawOval(x-r, y-r, 2*r, 2*r);
43
44 // Set the olor to blue for the hands
45 g.setColor(Color.blue);
46 // Draw the minute hand.
47 drawHand(g, x, y, r, minute/60.0);
48
49 // Draw the hour hand.
13.10. CUSTOM DRAWING IN SWING 55

50 drawHand(g, x, y, (int)(r*0.8), (hour+minute/60.0)/12.0);


51 }
52
53 private void drawHand (Graphi s g, int x, int y, int r, double fra tion) {
54 int x1, y1; // end point of a lo k hand
55 double theta; // angle from 12:00
56
57 theta = 2*Math.PI*fra tion;
58 x1 = x + (int)(r*Math.sin(theta));
59 y1 = y - (int)(r*Math. os(theta));
60 g.drawLine(x, y, x1, y1);
61 }
62 }

Noti e the alls to getWidth and getHeight in paintComponent; these


are methods that Clo k inherits from JPanel (whi h inherits them from
JComponent).
A lient that uses this new Clo k lass might look like this:
1 import javax.swing.*;
2 import java.awt.*;
3 import java.awt.event.*;
4
5 publi lass Clo kWithButtons extends ClosableJFrame
6 implements A tionListener {
7
8 Clo k = new Clo k();
9 JButton
10 bHour = new JButton("Advan e Hour"),
11 bMinute = new JButton("Advan e Minute");
12
13 publi Clo kWithButtons () {
14 JPanel buttonPanel = new JPanel();
15 buttonPanel.add(bHour, BorderLayout.WEST);
16 buttonPanel.add(bMinute, BorderLayout.EAST);
17 Container p = getContentPane();
18 p.setLayout(new FlowLayout());
19 p.add(buttonPanel);
20 .setPreferredSize(new Dimension(100, 100));
21 .setBa kground(Color.pink);
22 p.add( );
23 bHour.addA tionListener(this);
24 bMinute.addA tionListener(this);
25 pa k();
26 setVisible(true);
27 }
28
29 publi void a tionPerformed (A tionEvent e) {
30 int hour = .getHour(),
31 minute = .getMinute();
56 CHAPTER 13. JAVA SWING (OPTIONAL)

FIGURE 13.16: Snapshot of the Clo k program.

32 if (e.getSour e() == bHour)


33 hour++;
34 else
35 minute++;
36 .set(hour,minute);
37 repaint();
38 }
39 }

A sample s reenshot is shown in Figure 13.16.


This lient pla es within its frame two buttons and a Clo k ob-
je t, using the ow layout manager, then performs the normal pa k
and setVisible a tions. The lient is able to set the preferred size
and ba kground olor of the Clo k; again, these methods are inher-
ited from JPanel. As usual, the lient listens for button pushes, using
a tionPerformed, in rementing either hour or minute, as appropriate.
Then in line 36, we tell the Clo k obje t to hange its time.
In line 37, we have a all to a method we have not seen before,
repaint. This all has the ru ial purpose of informing the run-time
system that the lo k needs to be repainted. Some explanation is in
order.
Java's runtime keeps tra k of just when any omponent requires
redrawing { su h as when it has been overed and then un overed by
some other window, or when its frame has been dei oni ed. Another
o asion when redrawing is required is when a setText message is
13.11. JAVA AND THE WEB 57

sent to a JLabel. But how does the run-time system know when a
omponent needs to be redrawn? In our Clo k lass, whenever the
hour or minute is hanged, the lo k should be redrawn, but how ould
the run-time system possibly know this? In fa t, it doesn't. That is
why, whenever the time is hanged in a tionPerformed, we must ask
the system to redraw the lo k by alling repaint.

13.11 Java and the Web

Most readers of this book are familiar with the World Wide Web. You
use it whenever you use a web browser, su h as Nets ape Communi ator
or Mi rosoft's Internet Explorer. Browsers allow you to view home home pages
pages (also alled web pages) set up by other users on other omputers web pages
that are on the web. These home pages ontain text and images and,
less frequently, sound and animation. The omputer that provides the
home page is alled a server (or http server, for hypertext transport server
proto ol server); your omputer is the lient (although, at the same lient
time, it may be a server for other lients). Ea h home page has an
address, giving the server it is on and its lo ation on that server. This
address is alled a uniform resour e lo ator (URL). uniform resour e
Home pages are written in a omputer language alled hypertext lo ator
markup language (HTML), a language very di erent from Java. HTML hypertext markup
pages are typed into a le, like Java programs. They are not ompiled, language
but when a omputer on the web requests an HTML do ument, it
re eives the text in the le and uses it to reate the image that the
browser displays. In Se tion 13.11.1, we provide a qui k HTML primer,
enough for you to reate a simple home page with text and images.
For the most part, when you view a web page in a browser, it is
stati |that is, it does not move mu h. There are limited ex eptions,
but something as dynami as, for example, a video game ould not be
written as an HTML do ument. Simply put, HTML do uments annot
exploit the omputing power of the lient. Java applets an over ome
this limitation of web pages. Later in this hapter, we show how to
write applets and in lude them in your own web pages.

13.11.1 HTML

Books|large ones!|have been written about how to write web pages


in HTML. We will show you how to write simple HTML do uments
with some text and pi tures. If you are interested in learning more,
onsult one of those large books or just look at the HTML \sour e" for
pages as you surf; all web browsers provide a way to do this.
The simplest web page is one that has only text. Here is an
example:
58 CHAPTER 13. JAVA SWING (OPTIONAL)

FIGURE 13.17: A s reen dump showing the HTML do ument on


page 57 in IE.

1 <HTML>
2 <HEAD>
3 <TITLE> My first home page </TITLE>
4 </HEAD>
5 <BODY>
6
7 My name is Napoleon I, Emperor of Fran e.
8 I'm just learning HTML, so please be patient.
9 Soon, I will have the greatest home page in the
10 entire ivilized world.
11
12 </BODY>
13 </HTML>

Figure 13.17 is a shot from Mi rosoft's Internet Explorer showing


how it looks. There are several points to take from this web page.
First, the entire do ument is surrounded by lines ontaining <HTML> and
</HTML>. Words pla ed like this within angle bra kets are alled tags.
Many tags ome in pairs, indi ating the beginning and end of some part
of the HTML do ument. The <HTML> / </HTML> pair surrounds the
entire do ument. Within this pair, the <HEAD> / </HEAD> pair en loses
a <TITLE> / </TITLE> pair, whi h en loses the title; the browser pla es
this title at the top of its window. The <BODY> / </BODY> pair en loses
the rest of the do ument. Ea h HTML page should onsist of a head
followed by a body. (As you an see in the example, tags do not have
to go on a separate line.)
There are various ways to give the body of your home page some
stru ture. The simplest me hanism is to use headings and paragraphs.
The paragraph tag, <P>, simply leaves spa e in a do ument, orre-
sponding to the start of a new paragraph; it has no losing tag. There
are several heading tags, <H1>, : : :, <H6>, orresponding to di erent
heading levels. H1 is for the biggest headings (like hapter titles) and
H6 for the smallest (like subse tion titles). In pra ti e, some headings
may ome out the same size. This HTML do ument shows the use of
13.11. JAVA AND THE WEB 59

headings and paragraphs, as well as the <CENTER> tag pair to enter


the heading.
1 <HTML>
2 <HEAD>
3 <TITLE> Emperor Napoleon's Home Page </TITLE>
4 </HEAD>
5 <BODY>
6
7 <CENTER><H1>Napoleon I</H1></CENTER>
8
9 <P>
10 My name is Napoleon I, Emperor of Fran e.
11 I am a famous general and have onquered many ountries.
12 I'm most proud of my work at Austerlitz, and have always
13 felt that my generalship at Waterloo has been underestimated.
14
15 <P>
16 In my spare time, I like to do origami
17 and spend quiet evenings at home with my wife Josephine.
18 </BODY>
19 </HTML>
Figure 13.18 is a s reen dump of this web page. (Note that the
large H1 title is in the body of the HTML do ument; the title portion
of the web page simply provides the text displayed as the title of the
window.)
Many HTML tags in lude attributes, written as a name, an equal
sign, and a value (whi h is usually a string in quotes). Pi tures|GIF or GIF
JPEG 3 images stored in their own les| an be in luded in web pages JPEG
by using the IMG tag with the SRC attribute. It is ommon pra ti e to
store all images in a subdire tory, simply as a matter of organization.
This web page (whose s reen dump is shown in Figure 13.19) assumes
that the les me.jpg and grayline.gif are stored in the dire tory
images, a subdire tory of the one that ontains the HTML page.4
1 <HTML>
2 <HEAD>
3 <TITLE> Emperor Napoleon's Home Page </TITLE>
4 </HEAD>
5 <BODY>
6
7 <CENTER>
8 <IMG SRC="images/me.jpg">

3 GIF stands for graphi s inter hange format; JPEG stands for joint photographi experts
group.
4 You an nd lots of small images like these by sur ng the net. When an image shows up
in the web page you are viewing, your browser will allow you to save your own opy of it;
he k the do umentation for the browser.
60 CHAPTER 13. JAVA SWING (OPTIONAL)

FIGURE 13.18: A s reen dump showing the HTML do ument on


page 59 in IE.

9 <H1>Napoleon I</H1>
10 </CENTER>
11
12 <P>
13 <IMG SRC="images/greyline.gif">
14
15 <P>
16 My name is Napoleon I, Emperor of Fran e.
17 I am a famous general and have onquered many ountries.
18 I am most proud of my work at Austerlitz, and have always
19 felt that my generalship at Waterloo has been underestimated.
20
21 <P>
22 In my spare time, I like to do origami
23 and spend quiet evenings at home with my wife Josephine.
24 </BODY>
25 </HTML>

A key feature|really, the key feature|of HTML pages is their


ability to link to other HTML pages (as well as non-HTML les). Usu-
ally, links are highlighted in some way, and li king on them auses the
browser to load the linked page. To in lude a link, use the <A> / </A>
tag pair. The HREF attribute gives the address of the page you wish
to link to, and the text (or image) within the <A> / </A> pair is the
link. The following HTML do ument (s reen dump in Figure 13.20)
ontains one link to another page in this dire tory and one link to a
page on another server.
1 <HTML>
2 <HEAD>
3 <TITLE> Emperor Napoleon's Home Page </TITLE>
13.11. JAVA AND THE WEB 61

FIGURE 13.19: A s reen dump showing the HTML do ument on


page 59 in IE.
62 CHAPTER 13. JAVA SWING (OPTIONAL)

FIGURE 13.20: A s reen dump showing the HTML do ument on


page 60 in IE.

4 </HEAD>
5 <BODY>
6
7 <CENTER>
8 <IMG SRC="images/me.jpg">
9 <H1>Napoleon I</H1>
10 </CENTER>
11
12 <P>
13 <IMG SRC="images/greyline.gif">
14
15 <P>
16 My name is Napoleon I, Emperor of Fran e.
17 I am a famous general and have onquered many ountries.
18 I am most proud of my work at Austerlitz, and have always
19 felt that my generalship at Waterloo has been underestimated.
20
21 <P>
22 In my spare time, I like to do
23 <A HREF=
24 "http://www.yahoo. om/Re reation/Hobbies_and_Crafts/Origami/">
25 origami</A>
26 and spend quiet evenings at home with my wife
13.11. JAVA AND THE WEB 63

27 <A HREF="jojo.html">Josephine</A>.
28 </BODY>
29 </HTML>

You an reate your own simple home page using just the HTML
features we presented. For it really to be a web page, you must pla e
it on an http server with an appropriate name and in an appropriate
dire tory; ask your system administrator how to do this.
The features we have overed allow the reation of only \stati "
web pages. You may have seen a tive-looking web pages|for example,
those with animated GIFs or forms and sear h fa ilities|but HTML
provides very limited fa ilities for su h a tive pages. The purpose of
Java is to remedy this.

13.11.2 Applets and the APPLET Tag

Imagine you would like to provide a simple video game on the Internet.
You are willing to do all the work and provide the game for free. In
fa t, you will provide it to anyone who an a ess your home page.
But how? You might provide it as an exe utable le; but then users
have to download and store it and then exit their browsers to run it.
Furthermore, many will be unwilling to try it for fear of viruses. The
best solution would be to provide it as part of your home page, but
there is no way to write the game in HTML.
Here is where Java omes in. It an be used to write applets,
omputer programs that run within a window of your home page set
aside for the applet. The browser an guarantee that the applet annot
store unwanted data on your ma hine and does not arry a virus. With
a applet (or several!) running in your home page, it is truly an a tive
page.
Fortunately, all of the programs that we have written so far an be
transformed into applets! More pre isely, we an write a \shell" applet
that allo ates an instan e of any of the programs we have written so
far. On e your applet shell is written and ompiled into a . lass le,
you must write some HTML to in lude it in your web page. In your
web page you use the <APPLET> tag to open a window for the applet
and start it up.
<APPLET CODE=" lename. lass",
WIDTH= integer,
HEIGHT= integer>
</APPLET>
The <APPLET> tag gives the name of the lass le as the CODE attribute,
and the size of the applet's window as the WIDTH and HEIGHT attributes.
The HTML page in Figure 13.21 in ludes the \BodyMass" program as
an applet, whi h we will now explain. Noti e that the Java program
64 CHAPTER 13. JAVA SWING (OPTIONAL)

1 <HTML>
2 <HEAD>
3 <TITLE> Emperor Napoleon's Home Page </TITLE>
4 </HEAD>
5 <BODY>
6
7 <CENTER>
8 <IMG SRC="images/me.jpg">
9 <H1>Napoleon I</H1>
10 </CENTER>
11
12 <P>
13 <IMG SRC="images/greyline.gif">
14
15 <P>
16 My name is Napoleon I, Emperor of Fran e.
17 I am a famous general and have onquered many ountries.
18 I am most proud of my work at Austerlitz, and have always
19 felt that my generalship at Waterloo has been underestimated.
20
21 <P>
22 In my spare time, I like to do
23 <A HREF=
24 "http://www.yahoo. om/Re reation/Hobbies_and_Crafts/Origami/">
25 origami</A>
26 and spend quiet evenings at home with my wife
27 <A HREF="jojo.html">Josephine</A>.
28
29 <P>
30 Also, I am just learning to write applets!
31 Here is my first effort; I hope you like it:
32
33 <APPLET CODE="BodyMassApplet. lass" WIDTH=0 HEIGHT=0>
34 </APPLET>
35
36 </BODY>
37 </HTML>

FIGURE 13.21: An HTML do ument with an embedded applet.


13.11. JAVA AND THE WEB 65

Name Des ription


URL getCodeBase () Return the base URL from whi h this applet
was loaded.
Container getContentPane () Return the ontent pane of this applet.
URL getDo umentBase () Return the base URL from whi h the HTML
page ontaining this applet was loaded.
Image getImage (URL url) Return an image from the given URL.
String getParameter (String Return the value of the given parameter.
name)
void init () Called by the browser to inform this applet
that it has been loaded.
void start () Called by the browser to inform this applet
that it should start its exe ution.
void stop () Called by the browser to inform this applet
that it should stop its exe ution.

TABLE 13.22: Some methods of the JApplet lass. (Some of these


methods are inherited from super lass java.applet.Applet.

must spe ify the full le name for the program's . lass le, en losed
in double quotes. The size of the applet is set to 0  0 in line 33 be ause
we do not pla e anything expli itly in the browser window; we just run
the BodyMass program, whi h pops up its own frame.
The Java shell for an applet always has a parti ular form, as fol-
lows:
1 import javax.swing.*;
2 import java.applet.*;
3
4 publi lass BodyMassApplet extends JApplet {
5
6 publi void init () {
7 new BodyMass();
8 }
9 }

As you an see, the applet shell is almost trivial. As always, it


de nes a new lass having the same name as the le. The lass is a sub-
lass of JApplet, whi h is a lass de ned in the javax.swing pa kage;
the JApplet lass is summarized in Table 13.22. Consequently, lines 1
and 3 appear as you would expe t. The real di eren e is that the init
method is used instead of the main method. Within this init method,
we just allo ate the desired JFrame sub lass { BodyMass in this ase |
just as we had previously done in main.
Sometimes you want to modify a program so that it draws in the
applet's eld rather than in a separate pop-up frame. Our graphi al
66 CHAPTER 13. JAVA SWING (OPTIONAL)

programs an be transformed as follows:


1. Set the size that you want the applet to be in your HTML le.
2. Add the import java.swing.*; statement.
3. Change extends JFrame (or extends ClosableJFrame) to
extends JApplet.
4. Change the onstru tor heading to publi void init().
5. Eliminate any ode that is meaningless in an applet, su h as set-
ting the title, pa king, and resizing. (The reason that these are
meaningless is that there is no title in the applet portion of a
browser, and the HTML spe i es a xed size for the applet.)
So if we hange line 33 in Napoleon's HTML le to
33 <APPLET CODE="BodyMass. lass" WIDTH=200 HEIGHT=200>

and make the above hanges to BodyMass, turning it into an applet, we


get the results shown in Figure 13.22. The modi ed ode is:
1 import javax.swing.*;
2 import java.applet.*;
3 import java.awt.*;
4 import java.awt.event.*;
5
6 publi lass BodyMass extends JApplet
7 implements ItemListener, A tionListener {
8
9 // Determine Body-Mass-Index and Obesity
10 // Author: Deborah Mi kunas, O tober 13, 2002
11
12 // De lare and allo ate Components
13 JTextField
14 tHeight = new JTextField(5),
15 tWeight = new JTextField(5);
16 JLabel
17 lIndex = new JLabel("What is your body-mass-index? "),
18 lHigh = new JLabel("Is this onsidered high or not?");
19 ButtonGroup
20 gender = new ButtonGroup();
21 JRadioButton
22 maleRadio = new JRadioButton("Male", true),
23 femaleRadio = new JRadioButton("Female", false);
24 JPanel
25 p1 = new JPanel(), // line 1
26 p2 = new JPanel(), // line 2
27 p3 = new JPanel(); // line 3
28
13.11. JAVA AND THE WEB 67

FIGURE 13.22: A s reen dump showing the modi ed HTML do ument


with an embedded applet.
68 CHAPTER 13. JAVA SWING (OPTIONAL)

29 publi void init () {


30 //super("Body Mass Program");
31
32 gender.add(maleRadio);
33 gender.add(femaleRadio);
34
35 // Set Label properties
36 lIndex.setHorizontalAlignment(JLabel.CENTER);
37 lIndex.setFont(new Font("Helveti a", Font.PLAIN, 14));
38 lIndex.setForeground(Color.blue);
39
40 lHigh.setHorizontalAlignment(JLabel.CENTER);
41 lHigh.setFont(new Font("Helveti a", Font.BOLD, 18));
42 lHigh.setForeground(Color.red);
43
44 // Arrange Components
45 setLayout(new GridLayout(5,1));
46 p1.add(maleRadio);
47 p1.add(femaleRadio);
48 add(p1);
49 p2.add(new JLabel("Height (in meters):"));
50 p2.add(tHeight);
51 add(p2);
52 p3.add(new JLabel("Weight (in kilograms):"));
53 p3.add(tWeight);
54 add(p3);
55 add(lIndex);
56 add(lHigh);
57
58 // Register Component Listeners
59 tHeight.addA tionListener(this);
60 tWeight.addA tionListener(this);
61 maleRadio.addItemListener(this);
62 femaleRadio.addItemListener(this);
63 }
64
65 publi void itemStateChanged (ItemEvent e) {
66 // Respond to Item Events:
67 // 1. femaleRadio Che kbox
68 // 2. maleRadio Che kbox
69 ompute();
70 }
71
72 publi void a tionPerformed (A tionEvent e) {
73 // Respond to A tion Events:
74 // 1. tHeight TextField
75 // 2. tWeight TextField
76 ompute();
77 }
13.12. SWING IN DETAIL 69

78
79 private void ompute () {
80 double height = Double.parseDouble(tHeight.getText());
81 double weight = Double.parseDouble(tWeight.getText());
82 double bodyMassIndex = weight / (height * height);
83 boolean female = femaleRadio.isSele ted();
84
85 lIndex.setText("Your body-mass-index is " + bodyMassIndex);
86 if ((bodyMassIndex > 27.8) ||
87 (female && (bodyMassIndex > 27.3)))
88 lHigh.setText("This is onsidered high.");
89 else
90 lHigh.setText("This is not onsidered high.");
91 }
92 }

13.12 Swing in detail

Swing is a ompli ated pa kage with many lasses, ea h with many


elds and methods. We annot des ribe all of them, but we do want to
give a survey of some of the more popular lasses, and also warn the
reader about some notorious \got has."

13.12.1 Swing vs. AWT

We mentioned in bug alert 13.1 that the java.awt pa kage has a set of
omponents analogous to Swing omponents, su h as Frame, Button,
and TextField. Moreover, the lasses in the Swing pa kage are des en-
dants of AWT lasses | spe i ally, the Swing omponents are des en-
dants of JComponent, whi h is a sub lass of java.awt.Container. The
AWT pa kage pre eded the Swing pa kage by several years, and is still
heavily used, although Swing is mu h more powerful. What exa tly is
the onne tion between the two pa kages?
The essential distin tion between these sets of omponents is ap-
tured by the terms heavyweight omponent and lightweight omponent. lightweight
heavyweight
To understand these terms, we must step ba k a bit further and dis uss omponent
how omponents are implemented.
Every Java program runs on a omputer that is equipped with
an operating system (OS). The operating systems in widest use are operating system
Mi rosoft's Windows, Apple's Ma OS, and, from various vendors, Unix;
ea h has numerous versions. There are many other operating systems
with smaller user bases. For the purposes of this dis ussion, we an
think of an OS as providing two servi es:
1. The OS is an intermediary between the programs running on the
omputer and the I/O devi es onne ted to it. The running pro-
70 CHAPTER 13. JAVA SWING (OPTIONAL)

gram an ask the OS to produ e some output (on the monitor,


printer, speakers, et .) or obtain some input (from the keyboard,
mouse, et .). Sin e the program annot always know when input
is going to o ur | users type keys and li k mouse buttons at
random moments | there is a me hanism by whi h the OS an
inform the program of su h external events. This me hanism is
what we have referred to as the \event model."
2. The OS provides operations to reate ommonly used s reen ar-
tifa ts like windows, buttons, s roll bars, and su h. By providing
these operations, the OS saves appli ation programmers a lot of
dupli ated work, and ensures that all appli ations running under
the system have a similar \look and feel." If you have had the op-
portunity to run programs on omputers with di erent operating
systems, you will have seen that the windows and buttons and le
dialogs and so on are drawn di erently on ea h ma hine. At the
same time, all (or at least, most) of the programs running on one
ma hine have similar-looking omponents. That is be ause ap-
pli ations usually use the operations provided by the OS to draw
these omponents.
The rst kind of servi e provided by the OS is absolutely vital
| a program annod do anything if it is unable to pro ess output or
respond to events su h as mouse li ks. The se ond kind of servi e is
useful but not essential. Ea h appli ation ould, in prin iple, draw its
own omponents. (In se tion ??, we wrote a program that ontained
simple buttons, whi h we drew as simple re tangles. With more e ort,
there is no reason we ould not have drawn buttons that would look
just as good as | or, indeed, identi al to | the buttons appearing in
real programs.)
Here, then, is the entral distin tion between AWT omponents
and Swing omponents: AWT omponents are drawn by invoking the
pro edures provided by the OS; sin e their look is xed | and, to an
extent, limited | by the OS, these omponents are des ribed as heavy-
weight. Swing omponents are, for the most part, drawn dire tly onto
the s reen with no assistan e from the OS,5 these are alled lightweight.
Swing was reated to over ome a big problem reated by heavy-
weight omponents: in ompatibility. The behaviors of omponents pro-
vided by di erent operating systems are not exa tly the same. For ex-
ample, on a Ma intosh, the OS handles button presses and provided no
me hanism ....??? An a umulation of su h minor di eren es makes for
annoying in ompatibilities and for es the programmer to put in extra
e ort to ensure that his program runs on all major platforms. More-
over, the only way to avoid in ompatibilities is to write omponents
that have only behaviors supported by all systems. Thus, the power

5 The prin ipal ex eption is JFrame, whi h must all the OS to reserve spa e on the s reen.
Summary 71

of AWT omponents is limited to the \least ommon denominator"


among the operating systems to be supported. The Swing strategy is
to use only the servi es that are provided by all OS's | basi ally just
the ability to reserve some s reen spa e, to draw pixels in that spa e,
and to dete t mouse and keyboard events | and build all omponents
from s rat h. This way Swing an reate more powerful omponents
but at the same time maintain ompatibility a ross systems.
An in idental advantage of the lightweight approa h is that users
an de ne their own omponent styles | the so- alled \look and feel"
of the GUI | and plug them into the program. Normally, the program
wants to use the look and feel that is ommon to the appli ations on
whatever platform it is running on; there is always a way to use the
\native" look and feel of a system, and that is the default setting for
Swing. However, it is possible to hange the look and feel so that, for
instan e, a program running under Unix an have the look and feel of a
Ma intosh program. In prin iple, you ould even reate your own look
and feel. (This is, however, quite ompli ated and is beyond the s ope
of this book.)
In bug alert 13.1, we warned against mixing AWT and Swing
omponents in the same program. This is a onsequen e of the
lightweight/heavyweight distin tion. When a GUI is made up of OS-
drawn omponents, the OS ontrols the order in whi h they are drawn;
if the omponents are lightweight, then the Java run-time system has
omplete ontrol of this. Having omponents drawn, and redrawn,
at the orre t times is quite a ompli ated problem. Furthermore, if
graphi s are drawn in a window, these must be drawn at the orre t
time relative to the other omponents. These omplexities make it dif-
ult for lightweight and heavyweight omponents to oexist ami ably.
We dis uss this issue in more detail in following se tion.

13.12.2 Painting, repainting, and validating

THIS SECTION NEEDS TO BE WRITTEN

13.12.3 A tour of Swing omponents

THIS SECTION NEEDS TO BE WRITTEN

Summary
Graphi al programs an be written in Java without using our
CSLib, but instead using the Java APIs dire tly. The most important
pa kages for this purpose are javax.swing (the Swing API), java.awt
(the Abstra t Windowing Toolkit), and java.awt.event (the event
model, whi h we rst used in Chapter 11).
72 CHAPTER 13. JAVA SWING (OPTIONAL)

Swing ontains lasses for a wide variety of omponents | s reen


artifa ts that are part of a graphi al user interfa e. An appli ation will
normally start by opening a window on the s reen; this an be done
by reating a JFrame obje t and sending it the setVisible(true)
message. A JFrame has a border and it has a ontent pane; the latter
an be obtained by sending the getContentPane() message to the
frame. The ontent pane is a ontainer omponent | a omponent
that ontains other omponents. Components an be added to this
ontent pane by sending it the add( omponent) message. Thus, a
typi al appli ation has the form:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

lass MyApp extends JFrame {

... instan e variable de larations ...

MyApp () {
Container p = getContentPane();
... reate omponents ...
p.add( omponent1);
p.add( omponent2);
...
setVisible(true);
}

... methods definitions ...


}
The most ommonly-used omponents are:
 JLabel | a simple, non-editable pie e of text and/or graphi s
 JButton | similar to a JLabel, but rea tive (see below)
 JTextField | an editable text area
 JChe kBox | a li kable box
 JRadioButton | similar to a he k box, but intended for use in a
button group (see below) in whi h only one button an be sele ted
 JS rollBar | a s roll bar su h as the ones that appear on the
right-hand side of web browsers when web pages are too long
 JPanel | a simple, unadorned ontainer. JPanels have no ap-
pearan e of their own but are used to arrange other omponents
on the s reen, as explained below.
ButtonGroup is a lass whose obje ts ontain sets of JRadioButtons;
a button group is used to enfor e the rule that only one radio button
in a group an be sele ted at a time.
Summary 73

Most omponents are rea tive, meaning that the program needs to
take some a tion when the omponent is li ked or has text typed into
it. The AWT event model | to whi h we were already introdu ed in
Chapter 11 | is used for su h omponents. The pro edure for making
omponents rea t varies slightly among omponents, but always follows
a similar pattern. For example, to reate a button that responds to
being li ked, your program would have the form
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

lass MyApp extends JFrame implements A tionListener {

JButton b;

MyApp () {
Container p = getContentPane();
b = new JButton("button label");
p.add(b);
...
b.addA tionListener(this);
setVisible(true);
}

... methods definitions ...

void a tionPerformed (A tionEvent e) {


// a tion to be taken when button b is li ked
}
}
a tionPerformed will be alled whenever the user li ks the button.
If a JTextField is used instead of a JButton, a tionPerformed will
be alled when the user types the enter key in the text eld.
To make a he k box rea tive, hange the above as follows:
use implements ItemListener instead of A tionListener in the
lass header; all .addItemListener(this) for ea h he kbox ; de-
ne the method itemStateChanged (ItemEvent e). The latter will
be alled whenever any he k box is li ked; in it, the expression
e.getSour e() will return a referen e to the parti ular he k box
that was li ked. The same goes for radio buttons. For s roll bars
use implements AdjustentListener, addAdjustmentListener, and
adjustmentValueChanged(AdjustmentEvent e). Other types of re-
a tive omponents are similar variations on the same theme.
Another type of event that an appli ation might want to handle
74 CHAPTER 13. JAVA SWING (OPTIONAL)

are the window events, su h as losing a window. Like mouse events,


these are not asso iated with spe i omponents. An appli ation
registers itself by de laring itself to implement the WindowListener
interfa e, and sending itself the addWindowListener(this) message.
WindowListener requires the de nition of seven methods, listed in Ta-
ble 13.7.
When a ontainer is pla ed in a frame, the omponents it ontains
(the ones that have been added to it) are painted into the frame. Their
positions within the ontainer are not given by xed lo ations, but are
instead determined by a poli y embodied in the layout manager. In the
appli ation's onstru tor (normally), the all p.setLayout(layout
manager) sets the layout manager for the frame's ontent pane; other
ontainers (su h as JPanels) an set their own layout managers. The
all p.setLayout(new FlowLayout()) sets the layout to ow layout,
whi h pla es omponents from left to right, then top to bottom; new
GridLayout(m, n) divides the ontainer into m  n equal-sized boxes
and pla es the omponents into them, left to right and then top to
bottom. new BorderLayout() divides the ontainer into north, south,
east, west, and enter areas; omponents are expli itly pla ed into one
of these areas by alls like add( omponent, BorderLayout.NORTH).
A JPanel, in addition to being a generi ontainer obje t, an
behave like the DrawingBox lass of CSLib, in that you an draw lines
and ovals and other images into it. To do this, de ne a sub lass of
JPanel, say DrawingPanel, and de ne
publi void paintComponent (Graphi s g)

in DrawingPanel. You an reate a DrawingPanel obje t and pla e it


into a frame just as you would any other omponent. Whenever the
frame needs to be redrawn, paintComponent will be alled. Within
paintComponent, alls su h as g.drawLine(: : :) and g.drawOval(: : :)
an be used, with the same e e t as the orresponding methods in
CSLib's DrawingBox.
If there is ever a time when you want paintComponent to be alled,
you an for e this to happen by alling repaint().
Web pages are written in hypertext markup language, or HTML.
HTML do uments ontain tags, some in opening and losing pairs,
whi h allow the insertion of headings and pi tures. Applets are in luded
in web pages by using the APPLET tag:
<APPLET CODE=" lename. lass",
WIDTH= integer,
HEIGHT= integer>
</APPLET>
The essential parts of a Java applet are
import javax.swing.*;
Summary 75

publi lass Classname extends JApplet f

publi void init() f


...
g
g

Unlike an appli ation, an applet does not ontain a main method.


Its lass header must in lude the words extends JApplet.
Swing ontains many other omponents beyond the ones we have
overed, as well as numerous layout managers and other mis ellaneous
servi es. More details on Swing | and all the standard API's | an
be found in the on-line do umentation and the ex ellent tutorials at
java.sun. om.

Exer ises

1. Modify the Temperature program so that it gets a temperature


in degrees Fahrenheit and displays the equivalent Centigrade and
Kelvin temperatures.

2. In Se tion ?? on page ??, you wrote a program to al ulate the


pri e of a o ee order. Turn this appli ation into a graphi al
program with appropriately labelled text elds for input.

3. Reprogram the body mass program so that the message \This is


not onsidered high" is displayed in blue, 16 point Helveti a type,
while the message \This is onsidered high" is displayed in red,
40 point bold Helveti a type. Be sure to resize the window when
in reasing this message size.

4. Modify our CalendarApplet so that today's date is en losed in a


re tangle.

5. Modify our CalendarApplet so that the rst row of the alendar


body (\Sun Mon ... Sat") is displayed in magenta, bold, 16 point
Helveti a font.

6. Many ele troni devi es use seven-segment displays to show num-


bers. These displays onsist of seven straight lines as shown here
(with labels added for referen e):
76 CHAPTER 13. JAVA SWING (OPTIONAL)

e f

Zero is drawn with segments a, b, , e, f, and g; 1 is usually drawn


with lines and f; 2 with lines a, , d, e, and g; and so on. Write
a program with a text eld for input of a number between 0 and
9, whi h draws the seven-segment version of that number.
7. In Exer ise ?? on page ?? you wrote an appli ation to ompute
whether a person is eligible for andida y for Congress, given the
person's age and years of itizenship. Rewrite this as a graphi al
program, using two JTextFields for input.
8. In Exer ise ?? on page ?? you wrote a swit h statement to om-
pute the postage rate for an item, given the weight of the item
and the mail lass. Write a graphi al program to ompute and
display the postage rate. Use a JTextField to input the weight,
and use three grouped radio buttons to sele t the lass of mail.
9. In Exer ise ?? on page ??, you wrote a program in whi h users
entered RGB values (three numbers) and saw the orresponding
olor. Transform that program into a graphi al program with
text elds for input. Add to that program six buttons, labeled
Less red, More red, Less green, and so on. When one of these
buttons is pushed, the value in the orresponding JTextField is
in remented or de remented by 10, and the new olor is displayed.
10. Re all from Chapter 2 that olors are obje ts of lass Color, whose
onstru tors in lude a three-argument onstru tor in whi h three
integers between 0 and 255 supply the red, green, and blue (RGB)
omponents of the olor. A olor an be made redder by in reas-
ing the red omponent and likewise for green and blue. It an be
darkened by redu ing all three values and lightened by in reasing
them.
De ne a program ColorTest that ontains integers vari-
ables red, green, and blue, in the range 0 to 255, for the red,
green, and blue values of a olor. It has methods to modify these
variables individually, as well as to modify them all (that is, to
hange the brightness of the ombined olor). In addition, it has
Summary 77

methods getColor, getRedComponent, getGreenComponent, and


getBlueComponent. Ea h of these returns a Color obje t. For ex-
ample, getRedComponent returns the olor with RGB omponents
(red; 0; 0).The method getColor returns the olor with RGB om-
ponents (red; green; blue).
Your program should have buttons for hanging the three
hues (red, green, and blue) by a xed per entage, and for hanging
the brightness. Another button, labeled in rease or de rease,
indi ates in whi h dire tion the other buttons operate; li king on
it toggles it. For example, if the dire tion button says in rease,
then li king on the Red button will in rease the amount of
red shown; li king on the dire tion button hanges its label to
de rease, so that li king on the Red button de reases the amount
of red. The program should display boxes showing the red, green,
and blue omponents and the ombined olor, side by side (use
setBa kground and drawFillRe t); ea h time one of the buttons
is pressed, these olors need to be hanged.
11. Write a program to display a olor bar. You should have two
he kboxes, labeled Color 1 and Color 2, respe tively, and three
text elds, labeled Red, Green, and Blue. The user enters two
olors by rst li king on the Color 1 box and then entering in-
tegers (in the range 0 to 255) in the text elds, and then li k-
ing on the Color 2 box and entering integers in the text elds.
Given these two olors, say (r1 ; g1 ; b1 ) and (r2 ; g2 ; b2 ), show a bar
of olors onsisting of 10 narrow strips of olor, with the left-
most strip ontaining olor 1 and the rightmost strip ontaining
olor 2, and the eight strips in between ontaining shades between
those two olors. Spe i ally, if Ær = r2 r1 , and similarly for Æg
and Æb , then the olor strips should ontain (r1 ; g1 ; b1 ) ( olor 1),
(r1 + Ær =9; g1 + Æg =9; b1 + Æb =9), (r1 + 2Ær =9; g1 + 2Æg =9; b1 + 2Æb =9),
and so on.
12. Write a program to draw sine urves. Two text elds are used to
enter the lower and upper x values, x0 and x1 , and a urve sin x
is drawn between those two values. The urve should be drawn
by pi king an appropriate x in rement, Æx , and drawing lines from
(x0 ; sinx0 ) to (x0 + Æx ; sin(x0 + Æx )), (x0 + Æx ; sin(x0 + Æx )) to
(x0 + 2Æx ; sin(x0 + 2Æx )), and so on.

You might also like