Sei sulla pagina 1di 77

Chapter 8.

User Interfaces, events and the


AWT

Context of Unit 8

The purpose of this unit is to present the philosophy behind Java's graphical
user interface model, and to explore the classes required to implement
programs that exploit the model.

Objectives

Having successfully completed this unit you should be able to:

Implement applets that feature standard user interface elements,

Understand and implement applets that use the interface event model

Understand and use different Java container layouts

Study Planning

You should expect to spend approximately 9 hours studying this unit. You may
find it convenient to break up your study as follows:

Disk-based Content: 2¼
hours
Application: 3 hours
Set textbook Content: 1 hour
Reflection (On-line discussions, review 1 hour
questions):
Tutorial Work: 1 hour
Related Coursework: ¼ hour
Extension Work: ½ hour
Equipment/software required

 Sun Java 2 Platform (also known as Java Development Kit 1.3)


 TextPad 4.5
 A Web browser

Reading material & resources

Core texts (supplied with module material):

1. Java: how to program. H. M. Deitel and P. J. Deitel, 3rd edition, Prentice-Hall,


ISBN: 0-13-012507-5

Online Resources:

1. Frequently-asked questions
2. Java 2D graphics overview on Sun's Java Web site
3. Additional Source Code Examples
Introduction to Unit 8

Unit 8 - Assigned reading

Read chapter sections 12.1-12.7, 12.14-12.15 pp 557-581, 602-613


respectively of Chapter 12 of Deitel and Deitel

The graphical user interface

Most modern software systems present a graphical user interface, consisting


of windows (independent screen areas), menus, controls (buttons, icons) with
pointer input (e.g. mouse).

Such interfaces are often called WIMP interfaces (Windows, Icons, Menus and
Pointers).

The graphical interfaces provided by most modern operating systems look and
work similarly, but not identically. Technically, their implementation is totally
different. So how can Java programs run on any platform?

Most people expect the programs they use to have a graphical user interface
(GUI), particularly if the human-computer interaction is complex. Typical GUI
methods include selecting functions from menus, using a mouse to initiate
methods, and having a number of programs visible on the same screen.

A note about recent developments in Java

Java currently supports two related sets of classes for creating a graphical user
interface. The early scheme, called 'AWT' (abstract window toolkit) is gradually
being supplanted by a more sophisticated scheme called 'Swing'.

Swing classes are usually subclasses of corresponding AWT classes, offering


extended functionality. It is possible to understand the concepts of Swing
without understanding the concepts of the underlying AWT classes. However,
a better understanding can usually be gained by first learning the more
fundamental AWT system, and then later building upon this knowledge if
knowledge of Swing is required.
In this unit the Java graphical interface model and AWT classes are presented
and investigated. After completing this unit you will be in a position, should you
wish, to explore some of the extensions offered by the Swing classes.

Platform-independence of the user interface

To understand the philosophy behind the Java GUI model, it is necessary to


know a little about the market in which software development operates.

Throughout the world, most people using desktop computers are using IBM-
compatible PCs. Indeed, for many people this will be the only desktop computer
with which they are familiar. However, there are other desktop computers that
are used widely enough to form a substantial market for software.

Of the people who use PCs, many will be using Microsoft Windows. Many
people are surprised to find that this is not the only graphical user interface
available, even for PCs. People using alternatives to Microsoft Windows on PCs
are a minority, but an increasing one. These people will need to be supplied
with software as well as the Windows users.

As well as desktop PCs, there is an increasing number of portable and pocket-


sized computers. Many of these run variants of Microsoft's Windows Operating
System, but a much larger number do not. The two most widely-used pocket
computers (at least in Britain) are 3-Com's PalmPilot and Psion's Series 5. Both
these devices have a graphical user interface and in neither case is it related to
Microsoft Window. These machines also represent a large market for software.

One of the design goals in the development of Java was to provide a system
where the same program would work on all these different systems, with
minimal effort on the part of the programmer. Therefore, for each program
developed, the potential market for the product would be increased, perhaps by
a factor of ten. This is good for the developers, as it can lead to increased
profitability; it is good for the consumers, as it makes a wider range of software
available.

The mechanism that Java uses to make a program portable is to abstract the
user interface. In a sense, the Java programmer works with 'simplified models'
of user interface elements - the Java runtime system is responsible for mapping
these onto the real user interface.
What is the 'Abstract Window
Toolkit'?

When thinking about Java one must remember that Java was designed so that
programs developed using it would work identically on any computer with a
Java system, irrespective of hardware and operating system.

This means that the Java programmer must never be allowed to communicate
directly with the computer's operating system, or with the 'real' user interface;
this would make the program platform-dependent. All user interface actions are
mediated by the AWT (or Swing) classes. The Java program creates and
manipulates AWT objects, and these objects manipulate the 'real' user
interface. The way this is done should be of no concern to the Java programmer;
it is automatic.

This is the origin of the word 'abstract' in AWT. In the same way that an abstract
class provides a specification, but not implementation, and abstract window
specifies how a screen window should behave, but does not define how it does
this.

The figure below illustrates how a Java program use AWT (or Swing classes)
that hide, from the Java programmer, the actual interface elements on
whichever computer system the Java program is being executed on.

For example, to the AWT a screen window that has a border and can be
manipulated by the user with a mouse is abstracted as the 'Frame' class. It is
just a rectangle with given size and position, which receives events (more of
which later). The Frame can contain other objects. The exact appearance of a
Frame on the user's computer will depend on the type of computer and the
operating system it uses. The action the user has to take to close the window
will vary from one system to another.
This scheme provides platform independence by separating the 'abstract'
concepts of the graphical user interface from their concrete implementation on
a given system. Technically the 'real' user interface element that the user sees
is called the 'peer' of the abstract element the Java program manipulates.

AWT classes

There is an AWT class (or a Swing class) for each user interface element that
Java understands. AWT classes provide functionality that is common to all 'real'
elements of that class - for example an AWT 'button' has a label and can be
'pushed'.

AWT classes form a hierarchy (discussed later in this unit). The hierarchy can
be expanded through subclassing by the programmer to extend functionality (to
some degree).

For every user interface element that the user will see on the screen, there will
be an object of a particular class in the Java program. These classes may be
standard ones provided by the AWT, or created by the programmer. For
example, to create a button to display, we could write:

Button myButton = new Button("Click me");

(The argument supplied to the button constructor here is the text that will appear
on the button).

Applet class to display a button

To create a button in an applet window that looks as follows:

we can define an applet class (in a file called Button1.java):


// Button1.java
// A program that creates a button
// Kevin Boone, May 1999
import java.applet.Applet;
import java.awt.*;
public class Button1 extends Applet
{
public Button1()
{
Button myButton = new Button ("Click me");
add (myButton);
}
} // class

A simple HTML file can be used to make the appletviewer run the applet:
<BODY>
<APPLET CODE="Button1.class" height=100 width=200></APPLET>
</BODY>

Of course, we have not coded any actions to respond to the event of a user
clicking on the button with their mouse - so if the button is clicked nothing
happens.

Content Index Content Page # 8

Basic AWT classes

Objects of these classes have a familiar appearance on the screen. They are have the
property that it is unusual to display another object inside them (in fact, in Java it is impossible
to put an object inside one of these basic objects). All these objects (except Label) can
respond to mouse clicks and keypresses by sending events to their listeners. This technique
is described in more detail below.

The exact appearance of these objects depends to a large extent on the computer system
you are using, but they should all work in the same way. The pictures shown below were
taken from a Java program running on a Windows NT system. The appearance on other
system will be slightly different, as illustrated below.
Button

Objects of class button respond to mouse clicks.

List

A List is a simple list of text Strings. The user can select a particular item. Note
that the program must use the List's add() method to put the text items in the
list.

Choice

A Choice functions in the same way as a List, except that normally only the
selected item is visible. The other items appear when the Choice object is
selected by the user.

Label
A simple line of text. The user can't normally interact with this item.

TextField

A line of text that can be edited by the user.

TextArea

A TextArea is like a text field except that multiple lines can be entered.

CheckBox

An object that can be selected and deselected.

The AWT class hierarchy

For completeness, the following diagram shows the relationships between the
classes we have discussed so far. Remember the large arrow is the standard
UML symbol for the subclass relationship.
It is not necessary for you to remember the details of this model; it has been
included so that you can see how the various parts discussed so far, fit together.

AWT events and listeners

AWT components interact by sending events to one another. Events are


handled by listeners. For your program to interact with the user, it must define
listeners for its GUI components.

So far we have seen how to create a user interface which could be quite
complex. However, as yet the user interface has no means of interacting with
the rest of the program.

Consider a simple program: an applet that has one button. When the button is
clicked it does something (it doesn't matter what, at this stage). For the button
to do anything at all, we must define a listener for it. The listener is the object
that will be notified when the user clicks the button.

The type of listener to create will depend on the type of object. For buttons we
require an action listener (the full Java documentation describes the listeners
that are appropriate for each object). The method that defines a listener for the
button is addActionLister(). So to create a button, put it in the applet's display,
and define a listener we would write:
Button myButton = new Button ("Click me!");
add(myButton);

myButton.addActionListener(...);

where the dots (&) indicate something missing. What are we going to put in
place of the dots? It can be any object that is a subclass of ActionListener. Note
that ActionListener is an interface, not a class. We can make any object a
subclass of ActionListener, provided that it provides an implementation for the
methods that ActionListener specifies. If you refer to the on-line documentation,
you will find that it only specifies one method:
public void actionPerformed (ActionEvent e);

In simple cases, we may define the applet itself to be the action listener for the
buttons it contains. This method is not very flexible, but works well for simple
applets. So the outline of the applet so far is:
import java.awt.*

import java.awt.event.*;

import java.applet.Applet;

class MyApplet extends Applet implements ActionListener

public MyApplet()

super();

Button myButton = new Button ("Click me!");

add(myButton);

myButton.addActionListener(this);

public void actionPerformed (ActionEvent e)

// Do something here when the user clicks the button

} // class
The line

myButton.addActionListener(this);

means make 'this' (i.e., this applet) the listener for the button called 'myButton'.
Whenever the button is clicked, Java will call the method actionPerformed. The
ActionEvent object which is passed into the method can be used to distinguish
which button was clicked if the same listener is listening to a number of different
buttons.

A more sophisticated method for handling events is to use different classes to


act as listeners for each type of object in use. It is also possible to make objects
'listen' to themselves.

Example of a button and an action listener

Consider an applet that looks the following running:

When the button is clicked, a message 'ouch' is displayed in a dialogue window:

//<APPLET CODE = "Listener1.class" height = 100 width = 200></APPLET>


import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
public class Listener1 extends Applet implements ActionListener
{
String message = "";
public Listener1()
{
super();
Button myButton = new Button ("Click me!");
add(myButton);
myButton.addActionListener(this);
}
public void actionPerformed (ActionEvent e)
{
message = "ooch!!!";
repaint();
}
public void paint(Graphics g)
{
g.drawString(message,75,50);
}

} // class

Temperature conversion example

Example of input/output interaction using text field objects.

When the user enters the centigrade temperature e.g. an integer, followed by
the enter key, the Farenheit conversion is calculated and displayed .

When the applet runs it looks like this:


// <applet code = "TempConversion.class" width = 300 height = 200></applet>

1 import java.awt.*;
2
3 import java.applet.Applet;
4
5
6 import java.awt.event.*;
7
8 public class TempConversion extends Applet implements ActionListener {
9
10 Label CentrigradeLabel, FarenheitLabel;
11
12 TextField CentIn, FarOut;
13
14
int f, c, answer;
15
16
17 public void init(){
18
19 CentigradeLabel = new Label("Enter Centigrade temperature ");
20
21
CentIn = new TextField(5);
22
23
24 FarenheitLabel = new Label ("Temperature Farenheit ");
25
26 FarOut = new TextField(5);
27
28 add(CentigradeLabel);
29
30
31 add(CentIn);

CentIn.addActionListener(this);
add(FarenheitLabel);

add(FarOut);

public int convert(int x){

answer = (((9*x)/5)+ 32);

return answer;

public void actionPerformed( ActionEvent e){

if (e.getSource()==CentIn)

c = Integer.parseInt(CentIn.getText());

f = convert(c);

FarOut.setText(Integer.toString(f));

The Java event handling framework in the given example:

1. Line 4. The class TempConversion implements ActionListener


2. Line 6 The GUI variable CentIn is declared: TextField CentIn
3. Line 10 The new instance of the CentInt textField is created CentIn = new
TextField(5);
4. Line 14 The GUI is added to the Window so it can be displayed add(CentIn);
5. Line 15 informs the ActionListener that the CentIn object will respond to text
field events CentIn.addActionListener(this);
6. Line 23 actionPerformed will be invoked when an event i.e. value entered
into the TextField CentIn followed by the Enter key takes place passing this
information to the ActionEvent object e. The method getsource() will detect
which component caused the event. The operations that we want to take
place in the application are defined on lines 26 - 28.

AWT classes - Activities and Exercises

Activity 1 ButtonCount applet

Exercise 1 - Event handling in Button example

Exercise 2 - Event handling in TextField example

Container layouts

AWT container objects

The objects described above (Button, Menu. etc.) do not normally contain other
objects. However, AWT supports classes whose objects can contain other
objects. You will have seen at least one of these already: the Applet class. In
the AWT, all classes of this type are subclasses of Container. A container object
has no display of its own, but exists to contain other objects.

One of the most important of these is the Panel. A Panel is simply a blank piece
of screen into which other objects can be inserted. Panels are often used in
conjuction with the layout manager to create complex displays, as described
later.

Another important subclass of Container is the Frame, described below.

AWT Frame windows

When working with applets, the applet viewer or Web browser automatically
creates a screen window for your program's output to appear in. However, if
you are writing a stand-alone application (described in the next unit) your
program must create its own main window. Typically an object of class Frame
does this. The figure below shows the appearance of an empty Frame object
on a Windows system.
This can be created by:

Frame myFrame = new Frame("Run");

myFrame.show();

The show() method makes the frame visible on the screen.

Of course, an empty Frame is not particularly useful. The next unit describes
the role of the Frame class in providing stand-alone Java applications.

Example applet creating a frame

The following applet will create a separate, frame window, apart from the applet
window:
import java.applet.Applet;
import java.awt.*;
public class Frame1 extends Applet
{
public Frame1()
{
Frame myFrame = new Frame("A frame created by an applet");
myFrame.setSize( 300, 200 );
myFrame.show();
}
} // class
As with the menu frame example, since no code has been written to deal with
actions, you cannot close this frame window. However, when you close the
applet window, the frame object will be destroyed and its window removed.

The layout manager

The layout manager positions components inside a container (e.g., Panel). It


also re-positions components automatically when the contained size changes.

There are several different layout manager types, all subclasses of


LayoutManager. The layout manager may re-size components if they don't
have a fixed size.

The use of a layout manager relieves the programmer of the effort of managing
the screen layout when large numbers of components are in use, but it does
take some time to get used to. The great advantage of the layout manager is
that it usually responds sensibly to changes in the size of a program's main
window, by re-organizing the components so that they are all visible (if
possible). The disadvantage of a layout manager is that it is difficult to specify
exactly how the display should appear.

The default layout manager is called the 'flow' layout manager. As each new
object is added, it positions it to the right of the previous one. If there is no room
to do this, it positions it below and at the left-hand edge of the window. Thus the
order of placement of objects is the same as the order of reading English text.
There are other types of layout manager, as will be shown below.
Types of layout manager

The 'flow' layout manager places objects from left to right and top to bottom.
The 'grid' is similar, but it attempts to line up objects on a grid of a fixed size.
This will usually result in objects being spaced more widely than the 'flow' layout.

A 'border' layout has five regions: the centre and the four borders. Objects can
be placed specifically into any of these regions.

The 'card' layout is different in that it only displays one object at a time (like a
stack of cards). Methods are provided to select which object is currently on 'top',
and therefore visible.

a more sophisticated layout manager is GridBagLayout, see 13.15 of


Chapter 13 of Deitel and Deitel for further information

Selecting a layout manager

Changing the layout manager for a particular AWT object is straightforward: use
the setLayout() method
setLayout should be given the name of a new object of the appropriate layout
manager

For example, here is how to create a new Panel and spacify that it has a 'border'
layout.
Panel p = new Panel();
P.setLayout (new BorderLayout());

Complex layouts

Complex layouts in Java can usually be achieved by 'nesting' Panel objects


within one another.

Note the following:

 Panel objects are invisible, and exist only to contain other objects

 Each Panel can have a different layout manager

 Often some trial and error is required to achieve the desired effect

The example below shows how to achieve a more complex layout than is
offered by the standard layout managers. It uses a two-layer structure. The
overall layout is provided by a Panel with a border layout. The Panel has no
'real' (user-accessible) objects, but contains two other Panels. These in turn
contain the objects that the user sees.
An alternative approach is to use the 'grid bag' layout.

User interface design tools are useful for designing complex layouts; they
quickly show how the display will appear without compiling the program. This
allows the programmer to make changes to the layout structure and see the
effect immediately.

Containers and Layout Mangers - Activities and Exercises

Activity 2 - Designing a complex display

Exercise 3 - AWT containers and components

AWT classes and container layouts concept map

Each phrase in this concept map needs to be a hyperlink to the appropriate


glossary entry

As with the concept map from the earlier units, you can use the map below as
a way to retrieve glossary entries. You might wish to re-visit this concept map
(and perhaps create / extend it for yourself on paper) as you progress through
the module.
Activity 1 - ButtonCount applet

Write a Java applet that creates and displays a Button object and a Label with
a message displaying the number of times the Button has been pressed. The
display should look something like this:
Discussion of Activity 1

//<APPLET CODE = "ButtonCount.class" height = 100 width = 200></APPLET>


import java.applet.*;
import java.awt.*;
import java.awt.event.*;
public class ButtonCount extends Applet implements ActionListener
{
private Button button;
private int counter = 0;

public void init()


{
button = new Button("press me");
add(button);
button.addActionListener(this);
}
public void actionPerformed(ActionEvent e)
{
counter++;
repaint();
}
public void paint(Graphics g)
{
g.drawString(" the count of presses is " + counter,10,50);
}
}
Activity 2 - Designing a complex display

Implement a prototype for a fruit machine simulation using Java AWT similar to
the one displayed :

Discussion of Activity 2

There are many possible ways in which this can be done, the solution given below uses two types
of layout managers: the Grid and the Border layouts.

This was part of the coursework from Semester 1 2000/1.

import java.awt.*;
import java.io.*;
import java.applet.Applet;
import java.awt.event.*;
// prototype display
public class FruitMachine extends Applet {
private Button go,stop,query;
private TextField one,two,three;
private Panel buttons, textfields, message, display, welcome;
private Label prompt, response;
public void init(){
buttons = new Panel();
welcome = new Panel();
textfields = new Panel();
message = new Panel();
display = new Panel();
response = new Label(" You won £ 3.00 ");
prompt = new Label (" The CMT4120 Fruit Machine ");
welcome.add(prompt);
add(welcome);
display.setLayout(new BorderLayout());
buttons.setLayout(new GridLayout(1,3,5,5));
go = new Button(" GO ");
buttons.add(go);

buttons.add(query);
stop = new Button("Stop");
buttons.add(stop);
display.add("North", buttons);
one = new TextField(3);
textfields.add(one);
one.setText("5");
two = new TextField(3);
textfields.add(two);
two.setText("5");
three = new TextField(3);
textfields.add(three);
three.setText("5");
display.add("Center", textfields);
message.add( response);
display.add("South", message);
add(display);
}
}

Exercise 1 Event handling in Button example

Given the listing Listener1.java answer the following questions:

1. What interface does the Listener1.java implement?

2. How many AWT objects are there in this example, and what are they?

3. List the statements, which are messages to the button object.

4. When the user clicks the right hand button in the caption bar of the window
will the window close?

5. How would the applet behave if the statement add(myButton); was missing?

6. What is the purpose of the keyword this ?

7. How would the applet behave is the statement


myButton.addActionListener(this); was missing?

8. What would happen if the public void actionPerformed (ActionEvent e)


method was missing?

9. What is the role of the ActionEvent object?

10. Why is the method repaint() used?

Discussion of Exercise 1

1. ActionListener

2. A Button myButton and an applet Listener1.

3. myButton us sent the message addActionListener(this) , and both AWT objects


constructors.
4. Yes because it is an applet.

5. The button would not be displayed.

6. this is a special read only variable that contains a reference to the current object. In the
given example it ensures that the CentIn object will be registered with the
ActionListener.

7. There would be no response to the pressing of the button.

8. The applet would not compile, the actionPerfomed method must be implemented
because of the ActionListener interface.

9. The actionPerformed method will be invoked when an event takes place passing this
information to the ActionEvent object e. The ActionEvent class has useful methods for
identifying the particular object where the event occurred such as getSource making
it possible to instruct the application to perform the specific tasks required.

10. The repaint method will call the paint method when an event takes place so that the
applet redraws itself.

Exercise 2 Event handling in TextField example

Answer each of the following questions, giving a full explanation to justify your
answer.

1. What method has to be implemented in the TempConversion applet for the


ActionListener interface ?

2. Which of the variables in the example are objects (reference types)?

3. Which of the variables are not objects (scalar/simple/built in types)?

4. List the statements which are messages to the text field objects?

5. What is the purpose of the method Integer.parseInt(String s) on line 26?

6. What is the purpose of the method used on line 28 Integer.toString(int i)?

7. Explain how the convert(int x) method works i.e. where it is declared, where
invoked etc. giving the line numbers
8. Would the applet work if the two labels: CentigradeLabel, FarehneitLabel
were not used at all?

9. What would the display look like if the size of the window was 600 x 500?

10. What would happen if the input was not integer e.g if the user enters 25.5?

Discussion of Exercise 2

1. The actionPerformed metod

2. The two Labels CentigradeLabel, FarenheitLabel the two text fields CentIn, FarOut,
and the applet TemperatureConversion.

3. The integers f,c,anser.

4. addActionListener, getText, setText and the constructor calls.

5. All input and output in Java is string, and in this example as we need numeric integer
input, the string from the text field has to be converted to an integer.

6. The reverse operation is needed to display the numeric result in the text field so the
integer result i is passed as an argument (parameter) to the toString method.

7. The method is declare on lines 19-22 and invoked on line 27.

8. The applet would work and perform the requested tasks but with no labels.

9. The display would not be on two lines, presently it wraps around.

10. The calculation would not be performed, in other word unless the input was integer it
would be ignored.

Exercise 3 Containers and Components

Analyse the BallWorld.java example from Unit 2 and answer the following
questions:

1. How many AWT component types are there in the example and what are
they?
2. Are there any containers used in this example, if so what are they?

3. What is a Java AWT container?

4. Is a container also a component?

5. Is a component also a container?

6. What messages are sent to the Ball object?

7. What messages are sent to the Frame object?

8. Will the BallWorld Frame window close if the top right hand button is clicked?

Discussion of Exercise 3

1. Assuming that we are not using version 8 there are two. The Ball object(s) and the
BallWorld frame.

2. The Frame is a container.

3. An object that can contain other objects including other containers.

4. Yes it is a subclass of class component.

5. No, but every container is a component.

6. setColor, setXMotion, setYMotion, getX, getY, paint, move, bounce

7. show, the constructor.

8. No because it does not implement the WindowListener interface.

Review Question 1

What visible graphical user interface elements does the AWT principally
support?

Answer to Review Question 1


Buttons, check boxes, list boxes, choice boxes, text entry fields (multi-line and single line)
and menus

Review Question 2

Why does the Java AWT not provide support for round buttons or oval
windows?

Answer to Review Question 2

AWT provides functionality which is likely to be common across the whole range of
computers on which a Java program is likely to run. Few computers have built in support
for round screen objects, so this facility cannot be provided by the AWT. In any case, the
AWT developers could not provide support for every conceivable user interface element;
sometimes the programmer has to do some work as well!

Review Question 3

The ability to create programs with graphical user interfaces is clearly very
important in modern practice. Yet the Sun JDK tools have no graphical user
interfaces (with the exception of the applet viewer). Why? Under what
circumstances might it be better not to provide a GUI?

Answer to Review Question 3

There are at least two good reasons not to provide a GUI for a specific program. First, it
may be unnecessary. The program may be sufficiently simple that it doesn't need one.
The philosophy behind Microsoft Windows (rightly or wrongly) is that all programs,
however trivial, have a graphical user interface. However, to find out the amount of free
space on all the hard disks on a Unix system requires only the typing of the command df
(three keystrokes including 'enter'). The same method on a Windows '95 system requires
three mouse clicks for each disk, plus several to find and launch the 'My Computer'
window. A graphical user interface undoubtedly makes a program easier to learn to use;
however, in many cases it is not efficient for an expert user. Second, not all computers
have a GUI facility. Think in particular about the small computers that are embedded in
devices that use electronic equipment like video recorders and car engines. To develop
and debug applications on a computer without a GUI, the development tools have to work
without a GUI.

Review Question 4

Why can a menu bar not be added to an Applet, when it can to a Frame?

Answer to Review Question 4

The technical reason is that Applet is a subclass of Panel, which is a subclass of


Container. These are blank screen areas. In user interface practice, menu bars are
associated with windows, (e.g., with captions and borders). In Java, a window is
represented as a Frame object. Frame and Applet do not have any subclasses in common
in which it would be sensible to define functionality for showing a menu.

Despite the apparent reasonableness of this explanation, it would have been nice to have
the facility to display a menu in an applet.

Discussion Topics

There are many new concepts in this unit. If you want to discuss with your fellow
students or make comments about the concepts to them, use the on-line
facilities.

Discussion Topic 1 - Number of mouse buttons

The Apple Macintosh range of computers has traditionally had a mouse with
only one button. This means that to be fully portable, Java programmers cannot
rely on the user having access to a two-button or three-button mouse. However,
users who do have a mouse with more than one button ought not to be
constrained by this. How can the Java programmer attempt to satisfy both
groups of users?
Answer to Discussion Topic 1

Mouse buttons send events. Each mouse button sends a different event. It is possible to offer
multiple ways of generating a particular event, so for example an alternative to clicking the right
mouse button on a PC might be to be pressing <SHIFT> while clicking the single mouse button
on a Mac. Or perhaps a key could be pressed on the keyboard, that would result in some action
on the object over which the mouse pointer sits.

So general purpose Java programs can be written, to take advantage of local hardware, without
disadvantaging those with standard hardware. Such programs must be written to deal with
'abstract' event messages, for example DISPLAY_POPUP_MENU_REQUEST(), and the
program has been written to process multiple ways of generating these messages - so there might
be methods to process right button clicks, and clicks when <SHIFT> is held, both of which result
in the sending of a DISPLAY_POPUP_MENU_REQUEST() message.

Discussion Topic 2 - Critical evaluation of platform specific libraries

Manufacturers of some Java compiler products include class libraries that are
not platform-independent. Programmers that use these libraries run the risk of
their programs not being portable. For example, Microsoft's 'Visual J++' product
is shipped with class libraries that interact directly with the Windows user
interface. This allows the programmer to create displays that take advantage of
Windows elements that are not supported by AWT or Swing.

What are the advantages and disadvantages of using these vendor-specific


class libraries?

Answer to Discussion Topic 2

Advantages:

speed

can make use of system specific functions

smaller, more system specific software

However, advantages such as these are usually outweighed by the following


disadvantages:

loss of portability - the program can only run on one type of system
difficulty to maintain/add to program - only Java programmers with a knowledge of the
system specific features can work with the code

multiple versions and duplication of work for distribution to multiple systems - to offer a
program that takes advantage of local system features to more that one type of system
means that system specific code has to be written for each system to ship to - i.e. all of
the portability issues are lost, and multiple versions of the program have to be maintained
(so one change to program functionality means updating all different versions of the
software), possibly each version has to be developed and compiled on a system the same
as the destination system (and each program version has to be tested on each destination
system)

lack of forward compatibility (with new types of software system)

Reflection on Learning Experience

In your Learning Journal write up your experience of your learning on this unit.
Say what you thought was good or bad, what you had difficulty understanding,
and how you resolved your problems.

Additional content and Activities

AWT menu classes

AWT uses three main classes to manage and display menus, as shown in the
figure below. There is also a 'PopupMenu' class. A PopupMenu is like a Menu,
but usually appears when the user clicks the mouse and disappears after an
item has been selected.

The structure can be described as follows:


A MenuItem is the element that the user selects to carry out a specific action

A Menu is comprised of a number of MenuItem objects

A MenuBar is comprised of a number of Menu objects

A MenuBar can be placed at the top of a window (e.g., an applet).

The procedure for constructing a complete menu in Java will be described later.

Note: In Java, applets can't have menu bars. A menu bar can be added to a
Frame window (described later), so stand-alone applications can have menus.
Applets can have a 'pop-up' menu, that is, a menu which becomes visible when
the user clicks the mouse in the applet.

Example application with menu bar

Consider this application window:

The frame of this window has2 menus: 'File' and 'Help'. The 'File' menu has the
following items:

New

Open

Save

-------

Exit

and the 'Help' menu has a single menu item:

About
The Java code to generate this application is in listing: FrameMenu1.java.

NOTE

When running this application, since no actions have been created to deal
with events, in addition to the menus having no behaviour, you will have
to terminate the application by pressing CTRL-C in the console window
where you ran the application.

Sub-classing AWT classes

A simple way to allow additional functionality to be added to basic AWT classes.


There are limitations to the user interface elements that can be created this
way.

The easiest way to create a new user interface element is to define a subclass
of an AWT class that is similar.

For example, you could create a class called RedButton which was identical to
the standard Button class except for having a red background (the default is
grey). The code for this might look like:
public class RedButton extends Button
{
public RedButton (String label)
{
super (label);
setBackground(Color.red);
}
}

But we could not use this method to create, say, a round button, or a button that
pops up a message when the mouse moves over it. Why not? Class Button is
an abstraction of the 'real' button that appears on the display. It only offers
functionality that is common to all or most real computer systems. Few real
graphical user interfaces allow circular buttons to be created automatically, so
class Button cannot provide this. This is a necessary price to pay for portability,
but it can be very frustrating.

So how could you create a circular button? Probably the easiest way is to create
a subclass of a different AWT element. A good candidate here would be
Canvas. A Canvas object is simply a blank, rectangular region of the screen.
Your program would have to draw the button as it would appear, and take
appropriate action when the user clicks on it. This is significantly more complex
than subclassing Button.

Look back to the Button1.java applet - perhaps try changing it to use the
RedButton class above.

Using AWT objects together

One object is placed inside another, or attached to another, by using the add()
method. Objects can be added inside other objects which in turn are inside
other objects, giving a nested structure.

The overal layour is controlled by the Layout Manager (discussed later in this
unit).

This example shows how a Menu object (labelled 'File') is created, and menu
items 'Open', 'Save' and 'Exit' placed inside it.
Menu fileMenu = new Menu("File");
MenuItem openMenuItem = new MenuItem ("Open");
MenuItem saveMenuItem = new MenuItem ("Save");
MenuItem exitMenuItem = new MenuItem ("Exit");
FileMenu.add(openMenuItem);
FileMenu.add(saveMenuItem);
FileMenu.add(exitMenuItem);

This menu cannot be placed in an applet because a Menu must be part of a


MenuBar. So we need to create a MenuBar and put the menu in that:
MenuBar menuBar = new MenuBar();
menuBar.add(fileMenu);
Now we can put the menu in an window. In the window's constructor, we would
write:
add(menuBar);

If we want an applet to contain a text field and a list box we could write in the
applet's constructor:
TextField textField = new TextField();
List list = new List();
add(textField);
add(list);

The positions of the text field and the list box will depend on the size of the
applet in which they are being placed. If there is room to show them side-by-
side, the standard layout manager will place them like this. However, if there is
not room it will place one above the other. Each AWT object that can contain
other objects is assisted by a layour manager whose job it is to keep the objects
in an orderly arrangement.

Take another look at the application: FrameMenu1.java

Additional Activities - Menus and Events

Activity 3 - AWT test program

Exercise 4 - Creating a complex menu

Exercise 5 - Categories of events

AWT on different platforms

For comparison, the figures below show how the different AWT objects appear
on two different systems.

The first display was obtained on a Unix system. The second from a Windows
system.
Note that the components appear similar to the Windows versions shown
above, but not identical.

The Java Event Handling framework

Event handling in Java supported by the AWT package is an example of the


Obeserver design pattern. It is implemented by means of Listener interfaces.
Design patterns in general are examples of useful solutions for specific
problems.
Java util package supports the Observer design pattern, which the developer
can use to specify event handling outside the AWT framework.

From AWT to Swing

The Swing user interface model is a development of the AWT model. It has
more classes and supports a greater range of user interface elements. The
event handling process is similar in Swing and AWT.

The Swing package includes new elements such as:

splittable windows, with a different component in each half

tree-style list boxes (as seen in Windows 'Explorer')

'tooltip' pop-up windows

progress bars

tabbed dialog boxes

Using these components is not fundamentally different from using AWT


classes; you will still have to create objects of the appropriate classes, use the
layout manager to organise them, and define listeners to handle events.

Additional Activities - Containers and Layout Managers

Activity 4 - Extending the AWT Test program

Exercise 6 - Calculator example

Additional Computer Based Activities

Activity 3 - AWT test program

Write a Java applet that creates and displays an object of each of these types
Button

Label

Choice

List

Checkbox

TextArea

TextField

The display should look something like this.

Don't change the layout manager from the default 'flow' layout.

Resize the applet viewer's window and watch what happens to the elements on
the display.

Discussion/Suggestion solution to Activity 3


/*========================================================
AwtTest.java
Shows the appearance of the AWT componenets, and demonstrates
how the layout manager arranges components.
Kevin Boone, August 1999
============================================================*/
import java.applet.Applet;
import java.awt.*;
/*===========================================================
AwtTest class
===========================================================*/
public class AwtTest extends Applet
{
public AwtTest ()
{
super ();
setSize (300, 300);
setLayout (new FlowLayout());
add (new Button ("Button"));
add (new Label ("Label"));
Choice choice = new Choice ();
choice.addItem("Choice");
add (choice);
List list = new List ();
list.add("List item 1");
list.add("List item 2");
add (list);
Canvas canvas = new Canvas();
canvas.setSize (50, 50);
add (canvas);
add (new Checkbox ("CheckBox"));
TextArea textArea = new TextArea ("TextArea", 5, 30);
add (textArea);
TextField textField = new TextField ("TextField");
add (textField);
}
} // class

Activity 4 - Extending the AWT test program

Now change the layout manager to 'GridLayout' for a 3x3 grid.

Resize the applet viewer's window and watch what happens to the elements
on the display now.

Discussion/Suggestion solution to Activity 4

Change the statement:

setLayout (new FlowLayout());

to

setLayout (new GridLayout(3,3) );

When you resize the window now, the components stay in their positions on the grid.

Additional Exercises

Exercise 4 - Creating a complex menu

Menus usually contain text, but it is also common to use a 'separator' (a


horizontal line) to divide groups of menu items to make them easier to read. In
Java, we define a separator by creating a new MenuItem object whose text is '-
' (a single dash). Java recognises the dash and turns it into a separator.

With this in mind, write the Java statements that create a menu with the
following structure.

File

New

------
Open

Save

Save as…

-----

Exit

Edit

Cut

Copy

Paste

Help

Contents

Search…

-----

About…

Discussion/Solution to Exercise 4

MenuItem newMenuItem = new MenuItem ("New");


MenuItem openMenuItem = new MenuItem ("Open");
MenuItem saveMenuItem = new MenuItem ("Save");
MenuItem saveAsMenuItem = new MenuItem ("Save as...");
MenuItem exitMenuItem = new MenuItem ("Exit");
MenuItem exitMenuItem = new MenuItem ("Cut");
MenuItem exitMenuItem = new MenuItem ("Copy");
MenuItem exitMenuItem = new MenuItem ("Paste");
MenuItem exitMenuItem = new MenuItem ("Contents");
MenuItem exitMenuItem = new MenuItem ("Search");
MenuItem exitMenuItem = new MenuItem ("About");
MenuItem separator = new MenuItem ("-");
Menu fileMenu = new Menu("File");
Menu editMenu = new Menu("Edit");
Menu helpMenu = new Menu("Help");
fileMenu.add(newMenuItem);
fileMenu.add(separator);
fileMenu.add(openMenuItem);
fileMenu.add(saveMenuItem);
fileMenu.add(saveAsMenuItem);
fileMenu.add(separator);
fileMenu.add(exitMenuItem);
editMenu.add(cutMenuItem);
editMenu.add(copyMenuItem);
editMenu.add(pasteMenuItem);
helpMenu.add(contentsMenuItem);
helpMenu.add(indexMenuItem);
helpMenu.add(aboutMenuItem);
MenuBar menuBar = new MenuBar();
menuBar.add(fileMenu);
menuBar.add(editMenu);
menuBar.add(helpMenu);
add(menuBar);

Note that the order of appearance of the items in each Menu depends on the order they were
added using the add() operator. It does not depend on the order in which they were created.

Exercise 5 - Categories of events

It has been stated that Button objects send an event when they are clicked. This
is intuitive: the only purpose of a button is to be clicked, and then something
must happen. Using your intuition and experience of how graphical user
interfaces work, suggest what events will be sent by each of these objects.
Describe the events in English; don't try to guess the Java names. You may
have to refer back to the text to remind yourself what these objects represent.

Hint: there is at least one for each class. Because this is an exercise in intuition,
not knowledge, there are many possible correct answers.

List

Choice

Checkbox

TextField

TextArea

When you have made your list, look in the Java documentation for each class
and see if your intuition agrees with that of the Java developers. In the
documentation, look for methods with names like 'addXXXlistener', which 'XXX'
will tell you the type of listener being used.

Discussion/Solution to Exercise 5

Here is a list of possible events; it is not exhaustive and you may have others.

List

User has selected an item

User has double-clicked an item

User has operated the scroll bar

Choice

All those as for the List class, plus…

User has caused the list to appear ('drop down')

User has caused the list to disappear

Check box

User has checked the box


User has unchecked the box

Text field

User has typed a character

Text area

Same as TextField

Exercise 6 - Example program 'Calculator.java'

Study the example program Calculator.java and answer the questions in it.

Discussion/Solution to Exercise 6

1. The applet implements ActionListener and KeyListener because it receives events from its
buttons. These events arise when the user clicks the mouse (ActionListener) or presses the space
bar when a button is selected (KeyListener).

2. These constants are used in several different places in the program. If the program had to be
modified and these values had to be changed, it would be very difficult to figure out which part of
the program to change.

3. 'North' specifies to the BorderLayout class that the component is to be added in the top border
of the layout (It might have been better to use the word 'Top' but the Java developers decided on
'North')

4. lastOperator will contain the character '+', as this was set when the user clicked on the '+' button
(in the method 'processOperator()'. lastNumber will contain the number '2', as this was also set
when the user clicked on the '+' button. (When the user clicked '+', the number '2' would have
been in the display). The variable numberInDisplay will be set to the number currently in the
display, which is '3'. So we have all the information we need to carry out the calculation.

5. This is quite a subtle point. Well done if you got this right! If you are entering a number, you
might be planning to enter a number that starts with a zero (e.g., 0.1, 0.05). If you press the sign-
change key, the program should change the sign even if you have entered 0.0 (because you are
planning to enter a proper number). But 0.0 is the same as 0 if you are working in numbers, so
your typing would be erased if this was read as a number. So when the user enters a number it
is read as a string, to be sure that the users entry is not lost.
6. If you have just finished a calculation, then when you enter a digit it should replace whatever is
in the display and start a new number. The attribute clearOnNextDigit is set to true whenever the
next digit should cause the display to be cleared.

7. The method processButton() requires a String as a parameter. For example, if you click the
button marked '1' it expects to get a String containing the text "1". However, when the user presses
a key, the user sends an event that specifies the single byte corresponding to that key. The two
lines indicated construct a String containing this one byte.

http://www.yahoo.co.uk/Computers_and_Internet/Programming_Languages/JavaScript

Additional Review questions

Review Question 5

In the AWT menu model, what objects contain what other objects?

Discussion of Review question 5

A Frame contains a MenuBar. A MenuBar contains Menus. Menus contain MenuItems

Review Question 6

Objects of which AWT classes send events to an 'item listener'? (There are at
least two, and if you've done activity 2 fully you'll know what they are).

Answer to Review question 6

An ItemListener is used by List and Choice objects. The ItemListener receives events when the
user selects an item in the list.

Review Question 7

In the AWT menu model, what objects contain what other objects?
Answer to Review Question 7

A Frame contains a MenuBar. A MenuBar contains Menus. Menus contain MenuItems

Review Question 8

Objects of which AWT classes send events to an 'item listener'? (There are at
least two, and if you've done activity 2 fully you'll know what they are).

Answer to Review Question 8

An ItemListener is used by List and Choice objects. The ItemListener receives events
when the user selects an item in the list.

End of Unit Review


Before proceeding to the next unit you should go online and work through the
review questions. When you have completed the questions you will be able to
obtain the answers for future reference.

Your performance with these questions will not affect your grade for the module,
but may be monitored so that your tutor can be alerted if you are having
difficulty.

Please contact your tutor if you feel you have not done as well as you expected.

Now complete the end of unit review questions online.


Code listings

Note to implementers: Please ensure both plain, and colourized versions


of each listing are available

Also please provide a contents page for each unit's program listings.

Listing of Calculator.java

/*==========================================================

Calculator.java

This program simulates the simple 'four-function' calculator (the

sort that can only add, divide, subtract and multiply). Your

will see that although this appears very simple, in fact we

need quite an extensive program to implement it.

The applet simulates the buttons and display of the standard

pocket calculator, and should look like this when executed:

<img src=calculator.gif>

<p>

(If you aren't looking at the HTML version of this file, you won't see

the picture)
To signal that the user has tried to do something that is mathematically

impossible (specifically to divide something by zero) this program

uses the mechanism of 'exception throwing'.

The issue of exception handling is covered in more detail later in the

module; don't worry if it doesn't make much sense at the moment.

Kevin Boone, July 1999

==========================================================*/

import java.applet.Applet;

import java.awt.*;

// We must include java.awt.event.*, as this includes definitions of the

// event handling classes, like ActionEvent

import java.awt.event.*;

/*==========================================================

Calculator class

The Calculator class provides most of the functionality for this program. After

the definition of Calculator we will define a class called 'DivideByZeroException'

This is a very simple class that will be used to indicate a division-by-zero


error condition

==========================================================*/

/// QUESTION: why am I specifying 'implements ActionListener, KeyListener'

/// to this class?

public class Calculator extends Applet implements ActionListener, KeyListener

/*==========================================================

Variables of Calculator class

==========================================================*/

// MAX_INPUT_LENGTH is a constant indicating how large the number entered by

// the user can be. A Java `double' can store a value with a precision of

// about 17 digits. Therefore there is no point in allowing the user to

// enter numbers any bigger than this.

final int MAX_INPUT_LENGTH = 17;

/*

Display modes

The variable `displayMode' can take one of three values. For ease of reading

I have defined three constants to represent these values. It doesn't matter


at all what the values of these constants are (I have used 0, 1 and 2), as

long as they are all different.

The displayMode variable indicates what is currently being displayed. It

will either be the number being entered by the user (INPUT_MODE), the

result of the last calculation (RESULT_MODE) or an error message

(ERROR_MODE). This variable is very important to the correct function of

the program. For example, if the user types a digit when the program is

in INPUT_MODE, the program should append the digit to the number

currently in the display. If in RESULT_MODE or ERROR_MODE, the display

should be cleared and the new digit put at the start. In fact,

many of the methods in this class behave differently according to the

value of displayMode

*/

/// QUESTION: why have I defined constants for these values? In the program

/// I write `if (displayMode == ERROR_MODE)'; why don't I just write

/// `if (displayMode == 2)' ?

final int INPUT_MODE = 0;

final int RESULT_MODE = 1;

final int ERROR_MODE = 2;

int displayMode;

// displayLabel is the area of the applet in which all display will be shown.
// I have used a Java `Label' object for this.

Label displayLabel;

// clearOnNextDigit is set to `true' whenever an operator (`+', '-', etc) is

// typed. This causes the next digit entered to be the start of a new number.

boolean clearOnNextDigit;

// lastNumber is the number that was entered by the user before the last
operator.

// for example, if the user type '2' followed by '+', then lastNumber will be

// set to '2'

double lastNumber;

// lastOperator is the operator last typed by the user. If the user types a

// '+' sign (or clicks on the '+' button), then lastOperator is set to

// '+'. This variable's value is set to zero to indicate that no operator

// has been typed yet

char lastOperator;

/*==========================================================

Calculator constructor

This operator (as with all constructors) is executed when the new object

is created. In this case we create all the buttons (and the panels that

contain them), then reset the calculator

The layout of buttons in this Applet is quite complex. We have three groups
of buttons, one for digits, one for operators and one for 'controls'

(`=', `AC' and `C'). I'm not sure `controls' is the right word here, but

I couldn't think of a better one. So we create three `Panel' objects

to contain each group of buttons. A Panel is a blank screen area whose

job is simply to hold other objects. Associated with each Panel is a

layout manager. The job of the layout manager is to group the buttons in

the right order. For example, the button panel has a grid of buttons, with

four rows of three buttons like this:

7 8 9

4 5 6

1 2 3

. 0 +/-

So we set the layout manager for this panel to a new GridLayout object.

When we create the new GridLayout we specify `new GridLayout(4, 3)'

which means `create a new GridLayout with four rows of three columns'.

Having created the panels, we add the buttons. Finally we add all the

panels into a single panel (called `buttonPanel') and add this to the

applet. We also add the display area.


==========================================================*/
public Calculator()

super();

setLayout (new BorderLayout());

Panel buttonPanel = new Panel();

Panel numberPanel = new Panel();

numberPanel.setLayout(new GridLayout(4, 3));

addButtonToPanel (numberPanel, new Button("7"), Color.blue);

addButtonToPanel (numberPanel, new Button("8"), Color.blue);

addButtonToPanel (numberPanel, new Button("9"), Color.blue);

addButtonToPanel (numberPanel, new Button("4"), Color.blue);

addButtonToPanel (numberPanel, new Button("5"), Color.blue);

addButtonToPanel (numberPanel, new Button("6"), Color.blue);

addButtonToPanel (numberPanel, new Button("1"), Color.blue);

addButtonToPanel (numberPanel, new Button("2"), Color.blue);

addButtonToPanel (numberPanel, new Button("3"), Color.blue);

addButtonToPanel (numberPanel, new Button("."), Color.blue);

addButtonToPanel (numberPanel, new Button("0"), Color.blue);

addButtonToPanel (numberPanel, new Button("+/-"), Color.blue);

buttonPanel.add(numberPanel);

Panel operatorPanel = new Panel();


operatorPanel.setLayout(new GridLayout(4, 1));

addButtonToPanel (operatorPanel, new Button("/"), Color.green);

addButtonToPanel (operatorPanel, new Button("*"), Color.green);

addButtonToPanel (operatorPanel, new Button("-"), Color.green);

addButtonToPanel (operatorPanel, new Button("+"), Color.green);

buttonPanel.add(operatorPanel);

Panel controlPanel = new Panel();

controlPanel.setLayout(new GridLayout(4, 1));

addButtonToPanel (controlPanel, new Button("AC"), Color.cyan);

addButtonToPanel (controlPanel, new Button("C"), Color.cyan);

addButtonToPanel (controlPanel, new Button("="), Color.cyan);

buttonPanel.add(controlPanel);

displayLabel = new Label("");

displayLabel.setAlignment(Label.CENTER);

/// QUESTION: what does `North' mean here?

add(displayLabel, "North");

displayResult(0);

add(buttonPanel);
addKeyListener(this);

requestFocus();

// clearAll sets the variables of the Calculator object to

// initial values (this is the method that is called

// when the user clicks on the `AC' button

clearAll();

/*==========================================================

setDisplayString

This method sets the text in the display area to the specified string.

This hardly needs to be a method at all, as it is so simple. However,

it is called many many other methods, and using a method for this

function would make it much easier to modify the program if we chose a

different way to display data. Otherwise, a large number of lines would

have to be modified.

==========================================================*/
void setDisplayString(String s)

displayLabel.setText(s);

/*==========================================================
getDisplayString

This method gets the text currently in the display area. See the note for

`getDisplayString' above for details.

==========================================================*/
String getDisplayString ()

return displayLabel.getText();

/*==========================================================
clearAll

Sets the state of the calculator to the `just switched on' state, that is,

`0' in the display, ready to input digits, and the last operator equal to

zero (that is, there is no last operator). This method is called by the

constructor to initialize the Calculator, and whenever the user

clicks on `AC'

==========================================================*/
void clearAll()

setDisplayString("0");

lastOperator = 0;

lastNumber = 0;

displayMode = INPUT_MODE;

clearOnNextDigit = true;

}
/*==========================================================
clearLastEntry

Clears the number currently in the display. This is called when the user

clicks on the `C' button.

==========================================================*/
void clearLastEntry()

setDisplayString("0");

clearOnNextDigit = true;

displayMode = INPUT_MODE;

/*==========================================================
displayResult

Displays the specified number in the display area, and sets the variables to

indicate that a result is being displayed. Specifically this method sets

`clearOnNextDigit' to `true'. This means that as soon as the user types

a digit, the display will be cleared to make space for a new number.

==========================================================*/
void displayResult(double result)

setDisplayString(Double.toString(result));

lastNumber = result;
displayMode = RESULT_MODE;

clearOnNextDigit = true;

/*==========================================================
displayError

Displays the specified error message in the display area, and sets the

variables to indicate that an error message is being displayed. Specifically

this method sets `clearOnNextDigit' to `true'. This means that as soon

as the user types a digit, the display will be cleared to make space

for a new number.

The displayMode is set to ERROR_MODE to indicate that the display contains


an

error message and not a number. This is important because the user might

press a button that modifies the current number (like `+/-'). Clearly

we can't change the sign of an error message (or take its square root, etc).

==========================================================*/
void displayError(String errorMessage)

setDisplayString(errorMessage);

lastNumber = 0;

displayMode = ERROR_MODE;

clearOnNextDigit = true;
}

/*==========================================================
addButtonToPanel

This is a `convenience function', that is, it exists simply to reduce the

number of lines in the program (and therefore make it more convenient for the

programmer to manage). This method is called by the constructor to add

a new button to the display. It sets the buttons colour, and sets the

key listener and action listener to the appropriate methods (this has

to be done for every button, as we can't predict which button will have

the input focus at any given time).

==========================================================*/
void addButtonToPanel(Panel panel, Button button, Color backgroundColour)

panel.add(button);

button.setBackground(backgroundColour);

button.addKeyListener(this);

button.addActionListener(this);

/*==========================================================
actionPerformed

This method is called whenever the user clicks a button. This happens

because the method `addButtonToPanel' calls `addActionListener' for


every button. All this method does is pass on the text on the button to

`processButton'

==========================================================*/
public void actionPerformed (ActionEvent e)

processButton(e.getActionCommand());

/*==========================================================
processButton

This method takes action according to the user's input. It is called from

two other methods: actionPerformed (when user clicks a button) and

keyPressed (when the user presses a key on the keyboard). This method

examines the text on the button (the parameter `command') and calls the

appropriate method to process it.

==========================================================*/
void processButton(String command)

if (command.equals("0")) addDigit(0);

if (command.equals("1")) addDigit(1);

if (command.equals("2")) addDigit(2);

if (command.equals("3")) addDigit(3);

if (command.equals("4")) addDigit(4);

if (command.equals("5")) addDigit(5);

if (command.equals("6")) addDigit(6);
if (command.equals("7")) addDigit(7);

if (command.equals("8")) addDigit(8);

if (command.equals("9")) addDigit(9);

if (command.equals(".")) addDecimalPoint();

if (command.equals("*")) processOperator('*');

if (command.equals("-")) processOperator('-');

if (command.equals("/")) processOperator('/');

if (command.equals("+")) processOperator('+');

if (command.equals("=")) processEquals();

if (command.equals("+/-")) processSignChange();

if (command.equals("AC")) clearAll();

if (command.equals("C")) clearLastEntry();

/*==========================================================
getNumberInDisplay

Returns a double value indicating the number in the display. This method

should never be called if the display does not contain a number. When an

error message is being displayed, the value of `displayMode' is


ERROR_MODE,

so this can be used to test whether the display contains a number.

This method is only necessary to make it easier in future if we decide to

represent data on the display in a different way (i.e., to use a different

object rather than `Label')


==========================================================*/
double getNumberInDisplay()

String input = displayLabel.getText();

return Double.parseDouble(input);

/*==========================================================
processLastOperator

Carries out the arithmetic method specified by the last operator, the last

number and the number in the display.

If the operator causes an error condition (i.e., the user tries to divide

something by zero), this method can throw an execption.

==========================================================*/

/// QUESTION: if the user clicks on the buttons `2', `+' and `3', what values

/// will found in the variables `lastOperator' and `lastNumber', and the

/// variable `numberInDisplay'?

double processLastOperator() throws DivideByZeroException

double result = 0;

double numberInDisplay = getNumberInDisplay();


switch (lastOperator)

case '*':

result = lastNumber * numberInDisplay;

break;

case '+':

result = lastNumber + numberInDisplay;

break;

case '-':

result = lastNumber - numberInDisplay;

break;

case '/':

if (numberInDisplay == 0)

throw (new DivideByZeroException());

result = lastNumber / numberInDisplay;

break;

return result;

/*==========================================================
processOperator

Processes the operator most recently typed. All we do is evalute the

_last_ operator typed (not this one), and store this current variable

is `lastOperator' so it will get processed when the user types another


operator, or `='.

==========================================================*/
void processOperator(char op)

if (displayMode != ERROR_MODE)

double numberInDisplay = getNumberInDisplay();

if (lastOperator != 0)

try

double result = processLastOperator();

displayResult(result);

lastNumber = result;

catch (DivideByZeroException e)

displayError("Division by zero!");

else

lastNumber = numberInDisplay;

clearOnNextDigit = true;

lastOperator = op;

}
}

/*==========================================================
processEquals

Deals with the user clicking the `=' button. This method finishes the

most recent calculator. If the displayMode is `ERROR_MODE' (that is, the

display contains an error message) this method should not do anything.

==========================================================*/
void processEquals()

if (displayMode != ERROR_MODE)

try

double result = processLastOperator();

displayResult(result);

catch (DivideByZeroException e)

displayError("Division by zero!");

lastOperator = 0;

}
/*==========================================================
processSignChange

This method is called when the user clicks on the `+/-' (sign change)

button. If the number in the display is negative it is converted to positive.

If the number in the display is positive it is converted to negative. If

the number in the display is zero, nothing happens (as `-0' is meaningless).

This method behaves slightly differently depending on what mode the

display is in. If the user is currently entering a number, then it looks

at the _string_ in the display. If it is displaying a result it looks at

the _number_ in the display.

==========================================================*/
/// QUESTION: Why is this? Why does this method have to behave differently

/// depending on whether a result or a new number is in the display? Hint: it

/// is quite a subtle problem. The program would work correctly most of the

/// time if we always treated the display as a number.

void processSignChange()

if (displayMode == INPUT_MODE)

String input = getDisplayString();


if (input.length() > 0)

if (input.indexOf("-") == 0)

setDisplayString(input.substring(1));

else

setDisplayString("-" + input);

else if (displayMode == RESULT_MODE)

double numberInDisplay = getNumberInDisplay();

if (numberInDisplay != 0)

displayResult(-numberInDisplay);

// If displayMode is `ERROR_MODE' then this method should have no

// effect (because you can't change the sign of an error message!)

/*==========================================================
addDigit

This method is called when the user clicks a digit button, or types a

digit key. If the number currently being entered is less than 17 digits long,

then it adds the new digit to the end of the display.

==========================================================*/
void addDigit(int digit)
{

/// QUESTION: what are the next two lines for?

if (clearOnNextDigit)

setDisplayString("");

// We have to be careful to prevent the user entering ugly numbers

// like `000'. If the number in the display is `0', and the user

// clicks on `0', this display is not changed.

String inputString = getDisplayString();

if ((!inputString.equals("0") || digit > 0) && inputString.length() <


MAX_INPUT_LENGTH)

setDisplayString(inputString + digit);

displayMode = INPUT_MODE;

clearOnNextDigit = false;

/*==========================================================
addDecimalPoint

Called when the user clicks on the decimal point button. Puts a decimal

point on the end of the number currently being entered. If the number

already contains a decimal point, this method should do nothing

(that is, it should be impossible to enter a number like `1.2.3'


==========================================================*/

void addDecimalPoint()

{
displayMode = INPUT_MODE;

if (clearOnNextDigit)

setDisplayString("");

String inputString = getDisplayString();

// If the input string already contains a decimal point, don't

// do anything to it.

if (inputString.indexOf(".") < 0)

setDisplayString(new String(inputString + "."));

/*==========================================================
keyPressed

This method is called when the user presses a key, when any button has the

input focus. This happens because the method `addButtonToPanel' calls

`addKeyboardListener' for each button that it knows about. However,

this method does nothing in this program, as keyboard input is handled

in the method `keyTyped'. Because this applet is defined to `implement

KeyEventHandler' we have to provide this method, even if it does

nothing.

==========================================================*/
public void keyPressed(KeyEvent e)

{
}

/*==========================================================
keyReleased

Called automatically whenever the user presses and then releases a key. See

note for `keyPressed' for details

==========================================================*/
public void keyReleased(KeyEvent e)

/*==========================================================
keyTyped

This method is called when the user presses a key, and then releases it

when any button has the input focus. This happens because the method

`addButtonToPanel' calls `addKeyboardListener' for each button that it knows

about.

This method converts the key press to the text of the corresponding button,

then passes it to processButton to process. For example, if the user

presses `enter', this should have the same effect as clicking `='. So this

method calls `processButton' with the text `='. If the user

presses `escape' this should be treated the same as the `C' button. All other
keys are treated as digits. If the user presses a letter rather than

a digit, it will still be passed to `processButton', but processButton

will ignore it.

==========================================================*/
public void keyTyped(KeyEvent e)

String command;

char keyChar = e.getKeyChar();

if (keyChar == KeyEvent.VK_ENTER)

command = new String("=");

else if (keyChar == KeyEvent.VK_ESCAPE)

command = new String("C");

else

/// QUESTION: what do these next two lines do?

byte bytes[] = {(byte)keyChar};

command = new String(bytes);

processButton(command);

}
} // class

/*==========================================================
DivideByZeroException class

This class is used to indicate that the user has tried to divide a number

by zero (which is, of course, impossible. The Calculator applet should

respond by displaying an error message

The issue of exception handling is covered in more detail later in the

module; don't worry if it doesn't make much sense at the moment.

==========================================================*/
class DivideByZeroException extends Exception

DivideByZeroException()

super("Divide by zero");

Listing of FrameMenu1.java
// Menu1.java

// A program that creates a menu

// Matt Smith, Sep 1999


import java.applet.Applet;

import java.awt.*;

// This in an APPLICATION that extends Frame

public class FrameMenu1 extends Frame

public FrameMenu1()

// set up frame window title and size

super("a frame with a menu bar");

setSize( 300, 200 );

setVisible( true );

// set up menus

Menu fileMenu = new Menu("File");

MenuItem newMenuItem = new MenuItem ("New");

MenuItem openMenuItem = new MenuItem ("Open");

MenuItem saveMenuItem = new MenuItem ("Save");

MenuItem exitMenuItem = new MenuItem ("Exit");

MenuItem separator = new MenuItem ("-");

fileMenu.add(newMenuItem);

fileMenu.add(separator);

fileMenu.add(openMenuItem);

fileMenu.add(separator);

fileMenu.add(exitMenuItem);

Menu helpMenu = new Menu("Help");

MenuItem aboutMenuItem = new MenuItem ("About");

helpMenu.add(aboutMenuItem);

// add menus to menu bar


MenuBar menuBar = new MenuBar();

menuBar.add(fileMenu);

menuBar.add(helpMenu);

// make the frame use the menubar

setMenuBar( menuBar );

public static void main( String args[] )

// create an instance of our application class "FrameMenu1"

FrameMenu1 app = new FrameMenu1();

} // class

Listing of Button1.java
// Button1.java

// A program that creates a button

// Kevin Boone, May 1999

import java.applet.Applet;

import java.awt.*;

public class Button1 extends Applet

public Button1()

Button myButton = new Button ("Click me");

add (myButton);

} // class
Listing of Listener1.java
// Swing implementation

import java.applet.Applet;

import java.awt.*;

import java.awt.event.*;

import javax.swing.*;

public class Listener1 extends Applet implements ActionListener

public Listener1()

super();

Button myButton = new Button ("Click me!");

add(myButton);

myButton.addActionListener(this);

public void actionPerformed (ActionEvent e)

// Do something here when the user clicks the button

// display a window saying "ouch"

// (JoptionPane is a 'Swing' component)

JOptionPane.showMessageDialog(null, "ouch!");

} // class

Potrebbero piacerti anche