1 import acm.program.*;2 import java.awt.event.*;3 import java.awt.*;4 import acm.util.*;5 import javax.swing.*;6 import acm.gui.*;7 /*程序实现一个简单的四则运算计算器;*/
8 public class Calculator extendsProgram {9 /*初始的用户界面*/
10 public voidinit(){11 setLayout(new TableLayout(5,4));12 display = newCalculatorDisplay();13 add(display, "gridwitdh=4 height=" +BUTTON_SIZE);14 addButtons();15 addActionListeners();16 }17 //Called on each action event; the response is determined by the button
18 public voidactionPerformed(ActionEvent e){19 Object source =e.getSource();20 if(source instanceofCalculatorButton){21 ((CalculatorButton) source).action(display);22 }23 }24 //Adds the buttons to the calculator
25 private voidaddButtons(){26 String constraint = "width=" + BUTTON_SIZE + " height=" +BUTTON_SIZE;27 add(new DigitButton(7), constraint);28 add(new DigitButton(8), constraint);29 add(new DigitButton(9), constraint);30 add(newAddButton(), constraint);31 add(new DigitButton(4), constraint);32 add(new DigitButton(5), constraint);33 add(new DigitButton(6), constraint);34 add(newSubtractButton(), constraint);35 add(new DigitButton(1), constraint);36 add(new DigitButton(2), constraint);37 add(new DigitButton(3), constraint);38 add(newMultiplyButton(), constraint);39 add(newClearButton(), constraint);40 add(new DigitButton(0), constraint);41 add(newEqualsButton(), constraint);42 add(newDivideButton(), constraint);43 }44 //定义按钮大小的常量和实例变量
45 private static final int BUTTON_SIZE = 40;46 privateCalculatorDisplay display;47 }48
49 /*
50 * This class defines the display for the calculator.51 *52 * Implementation notes:53 * This class done most of the work for the calculator application and keeps54 * track not only of the number currently in the display but also the previous55 * operator button (op) and the previous value from the display (memory), which56 * will become the left operand of the operator. When a new operator button is57 * pressed, this class calculates the new value of the display by applying58 * that operator to the value in memory and the current value in the display.59 *60 * It is also important to note that the behavior of digit buttons depends on61 * whether an operator button is clicked. If the last click was an operator62 * button, the digit buttons must clear the display to start a new value. If63 * not, the digit is added to the end of the existing value. The code uses the64 * boolean variable startNewVlaue to record this state.65 */
66
67 class CalculatorDisplay extendsIntField {68 /*Creates a new calculator display that is not directly editable by the user*/
69 publicCalculatorDisplay(){70 setEditable(false);71 setFont(new Font("SansSerif", Font.PLAIN, 24));72 setValue(0);73 startNewValue = false;74 op = null;75 }76 /*Add a digit to the display, clearing the old value if startNewValue is set*/
77 public void addDigit(intdigit){78 int value = (startNewValue) ? 0: getValue();79 setValue(10 * value +digit);80 startNewValue = false;81 }82 //set a new operator , applying the previous one if one exists
83 public voidsetOperator(OperatorButton button){84 if (op == null){85 memory =getValue();86 } else{87 memory =op.apply(memory, getValue());88 setValue(memory);89 }90 op =button;91 startNewValue = true;92 }93 //private instance variables
94 private OperatorButton op; //The last operator button pressed
95 private int memory; //The value to which the operator is applied
96 private boolean startNewValue; //Set after an operator to start a new value
97 }98
99 /*
100 * This abstract class is the superclass for every calculator button. Every button101 * must define an action method, which is called whenever the button is clicked.102 */
103 abstract class CalculatorButton extendsJButton {104 //Create a new CalculatorButton with the specified name
105 publicCalculatorButton(String name){106 super(name);107 setFont(new Font("SanSerif", Font.PLAIN, 24));108 }109 //Called when the button is clicked (every subclass must implement this method)
110 public abstract voidaction (CalculatorDisplay display);111 }112 /*
113 * this class is used for each of the digit button. The action consists of114 * adding the digit used as a label on the button, which is returned by getText.115 */
116 class DigitButton extendsCalculatorButton{117 //Creates a new DigitButton for the digit n
118 public DigitButton(intn){119 super("" +n);120 }121 //Adds this digit to the display
122 public voidaction(CalculatorDisplay display){123 display.addDigit(Integer.parseInt(getText()));124 }125
126 }127 /*
128 * This abstract class is the superclass of the various operator buttons.129 * Each concrete subclass must override the apply method.130 */
131 abstract class OperatorButton extendsCalculatorButton{132 //Creates a new OperatorButton with the specified name
133 publicOperatorButton(String name){134 super(name);135 }136 //Informs the display that this operator button has been clicked
137 public voidaction(CalculatorDisplay display){138 display.setOperator(this);139 }140 //Applies this operator (every subclass must implement this method)
141 public abstract int apply(int lhs, intrhs);142 }143 /*
144 * The classes AddButton, SubstractButton, MultiplyButton, and DivideButton145 * are the same expect for their label and the implemention of apply.146 */
147 class AddButton extendsOperatorButton{148 public AddButton(){ super("+"); }149 public int apply(int lhs, int rhs){ return lhs +rhs; }150 }151
152 class SubtractButton extendsOperatorButton{153 public SubtractButton() { super("-"); }154 public int apply(int lhs, int rhs){ return lhs -rhs; }155 }156
157 class MultiplyButton extendsOperatorButton{158 public MultiplyButton(){ super("x"); }159 public int apply(int lhs, int rhs){ return lhs -rhs; }160 }161
162 class DivideButton extendsOperatorButton{163 public DivideButton() { super("/"); }164 public int apply(int lhs, int rhs) { return lhs /rhs; }165 }166
167 /*
168 * The EqualsButton class display the current value. As it happens, this169 * operation can be implemented simply by setting the operator to null.170 */
171 class EqualsButton extendsCalculatorButton{172 publicEqualsButton(){173 super("=");174 }175 public voidaction(CalculatorDisplay display){176 display.setOperator(null);177 }178 }179
180 /*
181 * The ClearButton class resets the calculator by setting the operator182 * to null and the display value to 0.183 */
184 class ClearButton extendsCalculatorButton{185 publicClearButton(){186 super("C");187 }188
189 public voidaction(CalculatorDisplay display){190 display.setOperator(null);191 display.setValue(0);192 }193 }