ÄúµÄλÖãºÑ°ÃÎÍøÊ×Ò³£¾±à³ÌÀÖÔ°£¾JavaÌìµØ£¾Core Java£¾Java Lecture Notes

previous.gif
 (3087 bytes)

next.gif
 (2959 bytes)


Extend Index

Extend Page # 21

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");

¡¡¡¡¡¡¡¡ }

}

 

 

Back to top

basicline.gif (170 bytes)