主函數:
import javax.swing.JFrame; public class Main { public static void main(String[] args) { CalFrame f = new CalFrame(); f.pack(); f.setVisible(true); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } }
四則運算:
package cal; import java.math.BigDecimal; /** * 四則運算 * @author lcp */ public class Math_lcp { private static BigDecimal BigDecimal(double num1) { // TODO Auto-generated method stub return new BigDecimal( num1 ); } //加法 public static double add(double num1, double num2 ) { BigDecimal first = BigDecimal( num1 ); BigDecimal second = BigDecimal( num2 ); return first.add(second).doubleValue(); } //減法 public static double subtract(double num1, double num2 ) { BigDecimal first = BigDecimal( num1 ); BigDecimal second = BigDecimal( num2 ); return first.subtract(second).doubleValue(); } //乘法 public static double multiply(double num1, double num2 ) { BigDecimal first = BigDecimal( num1 ); BigDecimal second = BigDecimal( num2 ); return first.multiply(second).doubleValue(); } //除法 public static double divide(double num1, double num2 ) { BigDecimal first = BigDecimal( num1 ); BigDecimal second = BigDecimal( num2 ); return first.divide(second, 20, BigDecimal.ROUND_HALF_UP).doubleValue();//四舍五入 } }
界面布局:
package cal; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Arrays; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JTextField; public class CalFrame extends JFrame { private JTextField textField = null; // 顯示計算結果的textField private String[] rOp = { "Back", "CE", "C" }; // 用一個數組保存結果操作符 // 用一個數組保存數字與其它操作符 private String[] nOp = { "7", "8", "9", "/", "sqrt", "4", "5", "6", "*", "%", "1", "2", "3", "-", "1/x", "0", "+/-", ".", "+", "=" }; private CalService service = new CalService(); // 業務邏輯類 private ActionListener actionListener = null; // 定義監聽器 private final int PRE_WIDTH = 360; // 設置panel的寬 private final int PRE_HEIGHT = 250; // 設置panel的高 public CalFrame() { // 默認構造器 super(); init(); } private void init() { // 初始化界面 this.setTitle("我的第一個計算器"); // 設置窗口的標題 this.setResizable(false); // 設置為不可改變大小 JPanel panel = new JPanel(); // 增加計算輸入框 panel.setLayout(new BorderLayout(10, 1)); panel.add(getTextField(), BorderLayout.NORTH); panel.setPreferredSize(new Dimension(PRE_WIDTH, PRE_HEIGHT)); JButton[] rButton = getRButton(); // 增加結果操作鍵 JPanel panel2 = new JPanel(); panel2.setLayout(new BorderLayout(1, 5)); JPanel panel21 = new JPanel(); // 新建一個panel,用於放置按鈕 panel21.setLayout(new GridLayout(1, 3, 3, 3)); // 設置布局管理器 for (JButton b : rButton) { // 迭代增加按鈕 panel21.add(b); } JButton[] nButton = getNButton(); // 增加數字與其它運算符 JPanel panel22 = new JPanel(); // 新建一個panel,用於放置按鈕 panel22.setLayout(new GridLayout(4, 5, 3, 5)); // 設置布局管理器 for (JButton b : nButton) { // 迭代增加按鈕 panel22.add(b); } panel2.add(panel21, BorderLayout.NORTH); // 把新增加的面板加到frame panel2.add(panel22, BorderLayout.CENTER); panel.add(panel2, BorderLayout.CENTER); this.add(panel); } public ActionListener getActionListener() { // 這個方法用來獲取監聽器 if (actionListener == null) { actionListener = new ActionListener() { public void actionPerformed(ActionEvent e) { String cmd = e.getActionCommand(); String result = null; try { // 計算操作結果 result = service.callMethod(cmd, textField.getText()); } catch (Exception e1) { System.out.println(e1.getMessage()); } if (result != null) { // 設置計算結果 textField.setText(result); } } }; } return actionListener; } private JTextField getTextField() { // 這個方法初始化輸入框 if (textField == null) { textField = new JTextField("0"); // 設置默認值為0 textField.setEditable(false); // 設置為不可編輯 textField.setBackground(Color.white); // 設置背景為白色 } return textField; } private JButton[] getRButton() { // 此方法獲得計算器的結果操作鍵 JButton[] result = new JButton[rOp.length]; for (int i = 0; i < this.rOp.length; i++) { JButton b = new JButton(this.rOp[i]); // 新建按鈕 b.addActionListener(getActionListener()); // 為按鈕增加事件 b.setForeground(Color.red); // 設置按鈕顏色 result[i] = b; } return result; } private JButton[] getNButton() { // 此方法獲得計算器的其它操作鍵 String[] redButton = { "/", "*", "-", "+", "=" }; // 這個數組保存需要設置為紅色的操作符 JButton[] result = new JButton[nOp.length]; for (int i = 0; i < this.nOp.length; i++) { JButton b = new JButton(this.nOp[i]); // 新建按扭 b.addActionListener(getActionListener()); // 為按鈕增加事件 Arrays.sort(redButton); // 對redButton排序,才可以使用binarySearch方法 // 如果操作符在redButton出現 if (Arrays.binarySearch(redButton, nOp[i]) >= 0) { b.setForeground(Color.red); } else { b.setForeground(Color.blue); } result[i] = b; } return result; } }
業務邏輯:
package cal; public class CalService { private double store = 0; // 存儲器,默認為0,用於保存需要暫時保存的計算結果 private String firstNum = null; // 第一個操作數 private String lastOp = null; // 去保存計算符號或者其它操作 private String secondNum = null; // 第二個操作數 private boolean isSecondNum = false; // 是否第二個操作數,如果是,點擊數字鍵時,則在文本框中重新輸入 private String numString = "0123456789."; // 數字 private String opString = "+-*/"; // 四則運算 public String callMethod(String cmd, String text) throws Exception { //調用方法並返回計算結果 if (cmd.equals("C")) { return clearAll(); } else if (cmd.equals("CE")) { return clear(text); } else if (cmd.equals("Back")) { return backSpace(text); } else if (numString.indexOf(cmd) != -1) { return catNum(cmd, text); } else if (opString.indexOf(cmd) != -1) { return setOp(cmd, text); } else if (cmd.equals("=")) { return cal(text, false); } else if (cmd.equals("+/-")) { return setNegative(text); } else if (cmd.equals("1/x")) { return setReciprocal(text); } else if (cmd.equals("sqrt")) { return sqrt(text); } else { return cal(text, true); } } /*如果secondNum為空,secondNum就等於最后輸入的數字,如果不為空,則等於原來的值,如果有“%”號操作,則secondNum再等於兩數相乘除以100的結果; * 然后根據lastOp的值(+、-、*、/)去調用MyMath類中的add、subtract、multiply、divide方法, * 並把返回的結果保存到firstNum;最后把secondNum設置為空,把firstNum當做結果返回。 * */ public String cal(String text, boolean isPercent) throws Exception { //四則運算isPercent,這是計算器的“%”號操作,如果有這種操作,第二個操作數就等於兩數相乘再除以100 // 初始化第二個操作數 double secondResult = secondNum == null ? Double.valueOf(text) .doubleValue() : Double.valueOf(secondNum).doubleValue(); if (secondResult == 0 && this.lastOp.equals("/")) { // 如果除數為0,不處理 return "0"; } // 如果有"%"操作,則第二個操作數等於兩數相乘再除以100 if (isPercent) { secondResult = Math_lcp.multiply(Double.valueOf(firstNum), Math_lcp .divide(secondResult, 100)); } if (this.lastOp.equals("+")) { // 四則運算,返回結果賦給第一個操作數 firstNum = String.valueOf(Math_lcp.add(Double.valueOf(firstNum), secondResult)); } else if (this.lastOp.equals("-")) { firstNum = String.valueOf(Math_lcp.subtract(Double.valueOf(firstNum), secondResult)); } else if (this.lastOp.equals("*")) { firstNum = String.valueOf(Math_lcp.multiply(Double.valueOf(firstNum), secondResult)); } else if (this.lastOp.equals("/")) { firstNum = String.valueOf(Math_lcp.divide(Double.valueOf(firstNum), secondResult)); } secondNum = secondNum == null ? text : secondNum; // 給第二個操作數重新賦值 this.isSecondNum = true; // 把isSecondNum標志為true return firstNum; } public String setReciprocal(String text) { // 計算倒數 if (text.equals("0")) { // 如果text為0,則不求倒數 return text; } else { this.isSecondNum = true; // 將isSecondNum標志為true return String.valueOf(Math_lcp.divide(1, Double.valueOf(text)));// 計算結果並返回 } } public String sqrt(String text) { // 計算開方 this.isSecondNum = true; // 將isSecondNum標志為true return String.valueOf(Math.sqrt(Double.valueOf(text))); // 計算結果並返回 } public String setOp(String cmd, String text) { //設置操作符號 this.lastOp = cmd; // 將此操作符號設置為上次的操作 this.firstNum = text; // 設置第一個操作數的值 代表下次輸入數字時,要清空輸入框並重新輸入。 this.secondNum = null; // 將第二個操作數賦值為空 this.isSecondNum = true; // 將isSecondNum標志為true return null; // 返回空值 } public String setNegative(String text) { // 設置正負數 if (text.indexOf("-") == 0) { // 如果text是負數,就將它變為正數 return text.substring(1, text.length()); } return text.equals("0") ? text : "-" + text; // 否則,將正數變成負數 } /*首先判斷是第一個操作數還是第二個,如果是第一個,就把用戶新輸入的數字追加到原來數字的后面,並做為結果返回; * 如果是第二個,直接返回結果,並把isSecondNum標志為false,用戶繼續輸入數字的時候,就把數字追加到原來數字的后面做為結果返回 */ public String catNum(String cmd, String text) { // 連接輸入的數字,每次點擊數字 把新加的數字追加到后面 String result = cmd; if (!text.equals("0")) { // 如果目前的text不等於0 if (isSecondNum) { isSecondNum = false; // 將isSecondNum標志為false } else { result = text + cmd; // 剛返回結果為目前的text加上新點擊的數字 } } if (result.indexOf(".") == 0) { // 如果有.開頭,剛在前面補0 result = "0" + result; } return result; } /*將用戶輸入的數字進行截取,如果接收到的字符串是“0”或者為null,則不作任何操作, * 直接返回,否則,我們將使用String的substring方法進行處理,將輸入字符串的最后一位截取 * */ public String backSpace(String text) { // 實現backspace功能 return text.equals("0") || text.equals("") ? "0" : text.substring(0, text.length() - 1); } /*清除所有計算結果,把firstNum與secondNum都設置為原始值,並返回firstNum, * 在CalService中提供了一個clearAll方法,用於清除所有的計算結果。 * */ public String clearAll() { // 清除所有計算結果 this.firstNum = "0"; // 將第一第二操作數恢復為默認值 this.secondNum = null; return this.firstNum; } public String clear(String text) { // 清除上次計算結果 return "0"; } public double getStore() { //返回存儲器中的結果 return this.store; } }