A Simple Calculator with a GUI


Objectives

In this lab, you will....

Pre-lab

The application: A Reverse Polish Notation Calculator

The calculator you will be working with uses Reverse Polish Notation (RPN), which avoids the ambiguities that can be caused by operator precedence and parentheses, but requires the calculator to remember many operands. RPN is just another name for postfix notation. In postfix notation, the operator  is specified after the operands instead of between the operands as in the more common infix notation. For example, the addition of 1 and 3 in infix would be: 1 + 3 and in postfix would be: 1 3 +. The best analogy for this would be pencil and paper arithmetic. With pencil and paper arithmetic, you write down the operands before you write down the operation. Using the same example you would write:

     1
   + 3
   -----
The RPNCalculator class uses the Stack class from Java's Collections library to hold the operands for pending operations, and to perform each operation on the last two operands pushed on to the stack. When an operation is entered, the top two operands (i.e. the numbers) are popped from the stack and the result of the operation is displayed and pushed onto the stack. Here is a sample run of the program to calculate 2 * (0.16 + 0.52):
   2
   0.16
   0.52
   +
   -----
   0.68
   *
   -----
   1.36
Note that it is possible to write expressions on a single line, but a space or carriage return (enter) needs to follow any operation.

Java SWING

The Java Swing classes allow you to build sophisticated user interfaces that behave uniformally across different platforms (e.g., Unix, Windows and the Mac) according to their "look and feel".

All the information that you will need for this lab can be found in the CPSC 219 Swing notes. There is also a wealth of tutorials on the Java Web site:

In addition, the full specification of classes and interfaces used in Swing can be found in the Java API. Most of what you will need  for this lab can be found in the javax.swing package.

Pre-Lab Exercise

Download the code for the lab (calculator.zip) and draw a UML diagram to represent the design. Inner classes can be represented by drawing a dependency arrow from the containing class to the inner class. If you are unsure about your answer, show your UML diagram to your TA. Try to draw the UML diagram before getting to the lab. It is important that you understand the structure of the code before the start of your lab as there will not be time to do it during your lab period.


In-lab Exercise

Your task is to create a graphical user interface (GUI) for a simple RPN calculator using Swing. Note that the first version of our calculator will only accept single-digit numbers (e.g. "7" but not "72").

To get started:

  1. Create the directory ~/cs211/labs/gui
  2. Create a new project in Eclipse called GUILab. Choose Create project from existing source and fill in the directory field with ~/cs211/labs/gui
  3. In the GUILab project, create a package called calculator
  4. Download the code for the lab (calculator.zip)
  5. Import the code into the calculator package (select the calculator package, right click and choose the Import wizard)

You should now have three files in the calculator package:

  1. CalculatorGUI.java - a start at the GUI for the calculator
  2. CalculatorTestGUI.java - a driver to run the GUI
  3. RPNCalculator.java - an implementation of an RPN calculator

The basic interface has already been implemented for you. You can see this interface by running the CalculatorTestGUI class as a Java application. However, when you run the program you will only see numerical buttons and one menu with only one item - "Quit". You need to add the following features to the CalculatorGUI class to make the GUI fully functional:

When you are done, your application will look something like:

Let us discuss each of the above features in more detail.

Operator Buttons

You can use the JButton class to represent the operator buttons. You will want to add each of the buttons to the opKeysPane JPanel. You may want to look at how the numeric keys are implemented for guidance.

Displaying the Stack

For displaying the stack of operands, a JTextArea that cannot be edited is probably the most appropriate choice. You may want to enclose the text area into a JScrollPane so that whenever the stack grows too large for the height of the window, a scroll bar appears, enabling the user to go back or forward and look at different parts of the stack. Note that to get the JScrollPane to work properly you will have to ensure that the JTextArea is set to wrap the lines of text rather than display it on one long line.

Menu Options

For the menu options, you should add the new options to the same menu that contains the "Quit" command. You will want to create a new JMenuItem for each of the commands, and then add it to an appropriate menu in the menubar.

ActionListener

Now the calculator interface looks like a simplified version of any calculator, and works perfectly... right? Not quite. As you will have noticed, pressing the buttons does absolutely nothing. That's because you will need to implement an ActionListener for every Swing object that you want to do something when triggered (in the case of a button, when pressed). You will notice that the CalculatorGui.java class implements ActionListener - an interface that enables objects in this class to react to certain triggers. You will also notice a method called actionPerformed(ActionEvent e). Any time a button or any other component is triggered, this method will be called. You will need to figure out what to do with the action once you receive it. This action should be general enough to apply to both numerical and operator buttons.

ActionListeners are the simplest (and easiest to implement) of a whole set of Event Handlers provided with Java Swing. You implement an action listener to respond to the user's indication that some implementation-dependent action should occur. For example, with a FocusListener, something would happen when an object gains or loses focus (like when you click on a textfield). For an ActionListener to be called, an action needs to happen, like the user pressing the button. Note that the FocusListener was mentioned simply to show you the distinction between different kinds of listeners. You do not have to worry about it for this lab.

For an overview of the different kinds of listeners, look here. For more on the ActionListener, just click the top link in the list on that page, How to Write an Action Listener. Also, don't forget the notes from CPSC 219.

Finally, you need to make sure that appropriate error messages get displayed. You will report errors by creating a pop-up message window with a description of the error. Notice that an errorPopup(String message) method has been implemented for you. You will need to call it at the appropriate time, with a reasonably descriptive message.

If your calculator works correctly, you should be able to calculate 4 * (6 + (5 / 2)) by clicking 4 6 5 2 / + * in that order.