一、计算器的界面:
1) 将这个JFrame窗口分为BorderLayout.NORTH BorderLayout.CENTER BorderLayout.SOUTH
2) 分别在三个部分(north center south)添加三个JPanel面板panel1 panel2 panel3
3) 将TextArea testArea添加到panel1中
4)将panel2设置布局为new GridLayout(4,4),再分别将14个JButton添加到panel2中
5)将panel3设置布局为new GridLayout(1,1)(目的为使添加的按钮填充panel3),再将JButton(也就是 “ = ” 按钮)添加到里面
得到以下布局:
二、程序代码
在我看来,实现这个程序的难点在于:
1.在ActionPerformed()方法中对获取的按钮事件的操作,也就是分类操作,其实这也就是这个程序的核心所在了,主要是这个算法,GUI做得再好看,这个算法不健壮的话程序还是很降档的。
解决:这个见仁见智,我的算法虽然基本可以实现,但对于一些挑剔的测试数据,比如 + + 9 - - . .等一些不正确的输入还是没能有相应的处理(就是今天比较懒,没处理这种异常,急着想发博文,过几天会有优化,会再发博文)
本程序ActionPerformed()算法基本分为:
a.对数字的处理
b.对计算符号的处理
c.对小数点的处理
d.对 = 符号的处理
e.对 c 符号的处理(清空符)
f.对 . 符号的处理
2.对小数点的操作,因为不能单单吧小数点的操作归处计算符号(+ - * /),所以需要用大段代码对小数点处理。
3.对double类型的精度计算,因为在计算double类型数的时候难免会出现精度混乱等问题,比如你计算的是3.1+3.00001,会出现 6.100010000000000001 的情况。
解决:使用BigDecimal类解决这个问题,可以很好的解决double类型数据的精度计算缺陷,具体实现:
public static double mul(double a,double b){
BigDecimal b1 = new BigDecimal(Double.toString(a));
BigDecimal b2 = new BigDecimal(Double.toString(b));
return b1.multiply(b2).doubleValue();
}
public static double add(double a,double b){
BigDecimal b1 = new BigDecimal(Double.toString(a));
BigDecimal b2 = new BigDecimal(Double.toString(b));
return b1.add(b2).doubleValue();
}
public static double sub(double a,double b){
BigDecimal b1 = new BigDecimal(Double.toString(a));
BigDecimal b2 = new BigDecimal(Double.toString(b));
return b1.subtract(b2).doubleValue();
}
public static double div(double a,double b) throws Exception{ //抛出了出现除数为0的异常
BigDecimal b1 = new BigDecimal(Double.toString(a));
BigDecimal b2 = new BigDecimal(Double.toString(b));
return b1.divide(b2,10,BigDecimal.ROUND_HALF_UP).doubleValue();
}
等到需要两个数计算时候就调用这四个方法就好了,不会出现精度混乱都问题。
实现ActionListener接口的ActionPerformed方法的算法很粗糙,但是确实正确,要是想要看懂的话估计有困难,我解释起来的也挺费劲的,所以就直接附上源代码,有兴趣的朋友可以拿去跑跑!
源代码:
package package2;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.math.BigDecimal;
/**
* Created by sakura on 16/5/23.
*/
public class Calculator extends JFrame implements ActionListener{
JButton bNumber[];
JButton bSign[];
String[] signSting;
static JTextArea testArea;
JPanel panel1,panel2,panel3;
static public int numberCount;
static public Double a;
static public Double b;
public double numberString[];
static String sign;
static int pointExist;
static int judgeException; //判断有 "除数为0" 异常时候testArea不输出内容
String timeSign;
Calculator(){
judgeException = 0;
timeSign = new String() ;
timeSign = null;
pointExist = 0;
sign = new String();
a = null;
b = null;
numberCount = 0;
numberString = new double[100];
bNumber = new JButton[20];
bSign = new JButton[20];
signSting = new String[]{"+","-","*","/",".","=","c"};
this.setVisible(true);
this.setBounds(300,100,600,600);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
/* 初始化组件 */
for(int i = 0;i < 10;i++){
bNumber[i] = new JButton(String.valueOf(i));
bNumber[i].addActionListener(this);
}
for(int i = 0;i < 7;i++){
bSign[i] = new JButton(signSting[i]);
bSign[i].addActionListener(this);
}
panel1 = new JPanel();
panel2 = new JPanel();
panel3 = new JPanel();
testArea = new JTextArea();
/* 将 textArea 添加到 BorderLayout.north*/
panel1.add(testArea);
/* 将panel2 设置为 gridlayout , 再添加到 BorderLayout.center*/
panel2.setLayout(new GridLayout(4,4));
panel2.add(bNumber[0]);
panel2.add(bSign[4]);
panel2.add(bSign[6]);
panel2.add(bSign[0]);
panel2.add(bNumber[1]);
panel2.add(bNumber[2]);
panel2.add(bNumber[3]);
panel2.add(bSign[1]);
panel2.add(bNumber[4]);
panel2.add(bNumber[5]);
panel2.add(bNumber[6]);
panel2.add(bSign[2]);
panel2.add(bNumber[7]);
panel2.add(bNumber[8]);
panel2.add(bNumber[9]);
panel2.add(bSign[3]);
/* 将 按钮 "=" 填充到 BorderLayout.south*/
panel3.setLayout(new GridLayout(1,1));
panel3.add(bSign[5]);
/* 将三个JPanel 添加到 JFrame*/
this.add(panel1,BorderLayout.NORTH);
this.add(panel2,BorderLayout.CENTER);
this.add(panel3,BorderLayout.SOUTH);
}
public static void main(String[] args) {
new Calculator();
}
public void actionPerformed(ActionEvent e){
timeSign = e.getActionCommand();
if (timeSign.equals("0") || timeSign.equals("1") || timeSign.equals("2") || timeSign.equals("3") || timeSign.equals("4") || timeSign.equals("5") || timeSign.equals("6") || timeSign.equals("7") || timeSign.equals("8") || timeSign.equals("9")) {
numberString[numberCount++] = Integer.valueOf(timeSign);
testArea.append(e.getActionCommand());
}else if (timeSign.equals("+") || timeSign.equals("-") || timeSign.equals("*") || timeSign.equals("/")) {
if(pointExist == 1 && b == null){
a = add(a,CalculatePoint(numberString,numberCount));
numberCount = 0;
}else if(pointExist == 1){
b = add (b,CalculatePoint(numberString,numberCount));
numberCount = 0;
}
if (a == null) {
sign = timeSign;
a = CalculateTotal(numberString, numberCount);
numberCount = 0;
} else {
if(pointExist == 0)
b = CalculateTotal(numberString, numberCount);
if(b != null)
a = CalculateTotalThree(a, b, sign);
sign = timeSign;
pointExist = 0;
}
numberCount = 0;
testArea.append(e.getActionCommand());
} else if (e.getActionCommand().equals("=")) {
if(pointExist == 1 && b == null){
a = add(a,CalculatePoint(numberString,numberCount));
numberCount = 0;
}else if(pointExist == 1){
b = add(b,CalculatePoint(numberString,numberCount));
numberCount = 0;
}
if (a == null) { //直接输入 = 的情况
testArea.append("=" + String.valueOf(a));
} else {
if(pointExist == 0)
b = CalculateTotal(numberString, numberCount);
if(b != null)
a = CalculateTotalThree(a, b, sign);
if(judgeException == 0)
testArea.append("=" + String.valueOf(a));
pointExist = 0;
judgeException = 0;
}
}else if(timeSign.equals(".")){
if(a == null ){
a = CalculateTotal(numberString,numberCount);
numberCount = 0;
pointExist = 1;
testArea.append(".");
}else {
b = CalculateTotal(numberString, numberCount);
numberCount = 0;
pointExist = 1;
testArea.append(".");
}
}else if(timeSign.equals("c")){
numberCount = 0;
pointExist = 0;
a = null;
b = null;
testArea.setText("");
judgeException = 0;
}
}
/* 自定义计算方法*/
public static double CalculateTotal(double number[],int i){ //计算从计算器读取到的数字的综总和
int total = 0;
int timeI = i;
i--;
for(int j = 0;j < timeI;j++){
total += number[j]*Math.pow(10,i--);
}
return total;
}
public static Double CalculateTotalThree(Double a ,Double b,String string){ //计算两个数在某一个符号下的值
if(string.equals("+"))
return add(a,b);
else if(string.equals("-"))
return sub(a,b);
else if(string.equals("*"))
return mul(a,b);
else if(string.equals("/"))
try{
return div(a, b);
}catch (Exception e){
testArea.setText(" 除数不能为0 ");
Calculator.a = null;
Calculator.b = null;
pointExist = 0;
numberCount = 0;
judgeException = 1;
}
return 0.0;
}
public static double CalculatePoint(double number[],int j){ //遇到小数点时候的情况
double total = 0;
int count = j;
for(int i = 0;i < j;i++){
total = add(total ,mul(number[i],Math.pow(Math.pow(10,i+1),-1)));
}
return total;
}
/* BigDecimal类方法,使计算更精确,优化double,解决出现结果不精确情况 */
public static double mul(double a,double b){
BigDecimal b1 = new BigDecimal(Double.toString(a));
BigDecimal b2 = new BigDecimal(Double.toString(b));
return b1.multiply(b2).doubleValue();
}
public static double add(double a,double b){
BigDecimal b1 = new BigDecimal(Double.toString(a));
BigDecimal b2 = new BigDecimal(Double.toString(b));
return b1.add(b2).doubleValue();
}
public static double sub(double a,double b){
BigDecimal b1 = new BigDecimal(Double.toString(a));
BigDecimal b2 = new BigDecimal(Double.toString(b));
return b1.subtract(b2).doubleValue();
}
public static double div(double a,double b) throws Exception{
BigDecimal b1 = new BigDecimal(Double.toString(a));
BigDecimal b2 = new BigDecimal(Double.toString(b));
return b1.divide(b2,10,BigDecimal.ROUND_HALF_UP).doubleValue();
}
}