作業要求
編寫Java GUI程序,實現一個簡單計算器。要求如下:
(1)設計的界面如下圖所示:窗體的標題欄顯示“模擬計算器—江海大”,1個文本框用於顯示輸入字符和計算結果;20個按鈕控件作爲字符輸入按鍵或者功能按鍵。
(2)計算功能:實現加、減、乘、除等雙目運算,開平方、百分數等單目運算;
(3)輔助功能:按鈕“C”清空文本框;按鈕“←”退格,刪除文本框中最右邊的一個字符。
代碼
爲了鍛鍊大家閱讀代碼的能力,本篇博文不包含代碼的詳細註釋,只說明幾點:
1、Java 不像 C / C++ 那樣具有手動釋放內存的函數。Java 由垃圾收集器(Garbage Collecter)來清除不再被變量引用的內存對象。
2、BigDecimal 對象一旦建立,不能修改。如果要修改某個 BigDecimal 變量的值,只能再次進行 new 操作。這個變量會指向內存中新建的新的 BigDecimal 的值,原有的 BigDecimal 成爲內存碎片,往後將被垃圾收集器自動回收(GC 一般不會立即回收不再被引用的對象)。
3、通過 BigDecimal 進行除法時,如果除不盡,會產生異常。本程序處理這個異常的方法是設定保留的小數位數(默認爲 64 位)並重新計算。
4、BigDecimal 類的成員變量中的指定四捨五入方式的常量已經棄用,指定四捨五入方式請通過 java.math.RoundingMode 中的常量指定。
5、由於時間關係,我沒有增加處理鍵盤響應的代碼,因此這個簡易計算器無法通過鍵盤輸入。這部分就暫時先鴿了,等我十分空閒時會考慮補充。
6、代碼橫向長度較長,建議複製到 IDE 中,將 IDE 的窗口最大化後再進行查看。
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.math.MathContext;
import java.math.RoundingMode;
import java.math.BigDecimal;
import java.math.BigInteger;
public class Calc {
public static void main(String[] args) { Main m = new Main(); }
}
class Global {
public static JTextField text = new JTextField("0");
public static final int scale = 64;
}
class Main {
JFrame frame = new JFrame("模擬計算器——江海大");
Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
JPanel panel = new JPanel(new GridLayout(5, 4));
Inputter inputter = new Inputter();
String name[] = { "C", "÷", "×", "←","7", "8", "9", "-", "4", "5", "6", "+", "1", "2", "3", "√", "%", "0", ".", "=" };
JButton button[] = new JButton[name.length];
Main() {
Global.text.setEditable(false);
frame.setLayout(new BorderLayout()); frame.setBounds(screen.width / 2 - 320, screen.height / 2 - 180, 640, 360);
frame.setResizable(false); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(panel, BorderLayout.CENTER); frame.add(Global.text, BorderLayout.NORTH);
for (int i = 0; i < button.length; ++i) {
button[i] = new JButton(name[i]); panel.add(button[i]); button[i].addActionListener(inputter);
}
frame.setVisible(true);
}
}
class Inputter implements ActionListener {
String t = new String(); int operator = 0;
boolean isRhs = false, decimalPoint = false, nextInput = false;
final String defaultString = new String("0");
final BigDecimal p = new BigDecimal(100); final MathContext m = new MathContext(Global.scale);
final BigInteger zero = new BigInteger("0");
BigDecimal x = new BigDecimal(0), y = new BigDecimal(0), z = new BigDecimal(zero, 0);
void compute() {
switch (operator) {
default:x = x.add(y); break;
case 1:x = x.subtract(y); break;
case 2:x = x.multiply(y); break;
case 3:
try { x = x.divide(y); }
catch (java.lang.ArithmeticException e) { x = x.divide(y, Global.scale, RoundingMode.HALF_UP); }
}
Global.text.setText(x.toString()); nextInput = true;
z = x; if (z == x) { decimalPoint = false; }
}
public void actionPerformed(ActionEvent e) {
String s = e.getActionCommand();
if (s.charAt(0) >= '0' && s.charAt(0) <= '9') {
if (nextInput) { Global.text.setText(s); nextInput = false; }
else {
t = Global.text.getText();
if (!t.equals(defaultString)) { Global.text.setText(t + s.charAt(0)); }
else { Global.text.setText(s); }
}
}
else if (s.charAt(0) == '.') {
if (decimalPoint == false) { Global.text.setText(Global.text.getText() + s.charAt(0)); decimalPoint = true; }
}
else if (s.charAt(0) == '%') {
if (isRhs == false) { x = new BigDecimal(Global.text.getText()); x = x.multiply(p); Global.text.setText(x.toString()); }
else { y = new BigDecimal(Global.text.getText()); y = y.multiply(p); Global.text.setText(y.toString()); }
}
else if (s.charAt(0) == '√') {
if (isRhs == false) { x = new BigDecimal(Global.text.getText()); x = x.sqrt(m); Global.text.setText(x.toString()); }
else { y = new BigDecimal(Global.text.getText()); y = y.sqrt(m); Global.text.setText(y.toString()); }
}
else if (s.charAt(0) == '+') {
if (isRhs == false) { x = new BigDecimal(Global.text.getText()); operator = 0; nextInput = true; isRhs = true; }
else { y = new BigDecimal(Global.text.getText()); compute(); isRhs = true; }
decimalPoint = false;
}
else if (s.charAt(0) == '-') {
if (isRhs == false) { x = new BigDecimal(Global.text.getText()); operator = 1; nextInput = true; isRhs = true; }
else { y = new BigDecimal(Global.text.getText()); compute(); }
decimalPoint = false;
}
else if (s.charAt(0) == '×') {
if (isRhs == false) { x = new BigDecimal(Global.text.getText()); operator = 2; nextInput = true; isRhs = true; }
else { y = new BigDecimal(Global.text.getText()); compute(); }
decimalPoint = false;
}
else if (s.charAt(0) == '÷') {
if (isRhs == false) { x = new BigDecimal(Global.text.getText()); operator = 3; nextInput = true; isRhs = true; }
else { y = new BigDecimal(Global.text.getText()); compute(); }
decimalPoint = false;
}
else if (s.charAt(0) == '←') {
t = Global.text.getText(); if (t.charAt(t.length() - 1) == '.') { decimalPoint = false; }
if (t.length() > 1)Global.text.setText(t.substring(0, t.length() - 1));
else Global.text.setText(defaultString);
}
else if (s.charAt(0) == 'C') {
isRhs = decimalPoint = false; Global.text.setText(defaultString);
x = BigDecimal.valueOf(0); y = BigDecimal.valueOf(0);
}
else if (s.charAt(0) == '=') {
if (isRhs) { y = new BigDecimal(Global.text.getText()); compute(); isRhs = false; }
}
}
}
簡單測試
初始界面
11111111111111112222222222222222+33333333333333335555555555555555
1.2 * 3.4 * 5.6 * 7.8
根號2(開平方的默認精度爲64位)
2 ^ 2 ^ 2 ^ 2 ^ 2 ^ 2 ^ 2 ^ 2 ^ 2(^代表乘方)
輸入2,按乘號9次。
114514666-123456-587
60/2/3/5/7(除不盡時默認截斷成64位)