Java Swing实现仿win7计算器

首先说明此代码的界面布局基本上参考了: http://yuncode.net/code/c_50b0c000f0c2e62由于后面的运算符处理操作实在难以理解。
所以后面事件的处理是自己改写的,我觉得这样比较好理解。

/**
 * 
 */
package myJavaSwing;
import javax.swing.JFrame;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JButton;
import javax.swing.JTextField;
import javax.swing.JPanel;
import java.awt.GridLayout;
import java.awt.Color;
import java.awt.BorderLayout;
import java.awt.Container;

/**
 * @author 花花
 *简介:仿windows7计算器
 *由于M键设计到存储器暂不支持M键的功能
 *
 */
public class Calculator extends JFrame implements ActionListener {
    //计算器的三个功能键名字
    private final String COMMAND[]= {"Backspace","CE","C"};
    //计算计算面板上的键名
    private final String CALCULATE[]= {"7","8","9","/","sqrt","4",
            "5","6","*","%","1","2","3","-","1/x","0","+/-",".","+","="};
    //计算器上的M键名
    private final String  M[]= {" ","MC","MR","MS","M+"};
    //定义三个功能按钮
    JButton commands[]=new JButton[COMMAND.length];
    //定义计算面板班的按钮
    JButton calculate[]=new JButton[CALCULATE.length];
    //定义M按钮
    JButton m[]=new JButton[M.length];
    //结果文本框
    JTextField resultText=new JTextField();
     //计算结果
     private double result=0;
     //文本框中之前是否有输入
     private Boolean preferExist=false;
     //操作符
     private String op="=";
     //是否按了操作符
     private Boolean operate=false;
     //中间值。如果连续操作,记录之前的值,避免被新值覆盖。
     private double beforebefore=0;
    //构造函数
    public Calculator() {
        super();//调用JFrame的构造方法,画出一个框架,其实可以不写,因为子类在构造时首先会调用父类的构造方法
        //初始化计算器
        init();
        // 设置计算器的背景颜色
        this.setBackground(Color.LIGHT_GRAY);
        this.setTitle("计算器");
        // 在屏幕(500, 300)坐标处显示计算器
        this.setLocation(500, 300);
        // 不许修改计算器的大小
        this.setResizable(false);
        // 使计算器中各组件大小合适
        this.pack();

    }
    //初始化计算器
    private void init()
    {   
        this.setTitle("计算器");//相当于构造方法Calculator()中的super("计算器");

        //文本框
        //结果文本框中的内容采用右对齐方式
        resultText.setHorizontalAlignment(JTextField.RIGHT);
        //文本框中的内容为只读方式
        resultText.setEditable(false);
        //设置文本框背景为白色
        resultText.setBackground(Color.white);
        /*建一个面板放文本框
         * 布局:边界布局*/
        JPanel resultPanel=new JPanel();
        resultPanel.setLayout(new BorderLayout());
        resultPanel.add(resultText);

        //初始化计算器上用于计算区域键的按钮,将这些键放在一个面板内
        JPanel calcPanel=new JPanel();
        //设置计算区域的面板布局,采用网格布局,4行5列,各组件之间的水平,竖直间隔都为3个像素
        calcPanel.setLayout(new GridLayout(4,5,3,3));
        for(int i=0;i<calculate.length;i++)
        {
            calculate[i]=new JButton(CALCULATE[i]);
            calcPanel.add(calculate[i]);
            //将这些键的字体颜色设为蓝色
            calculate[i].setForeground(Color.blue);
        }
        //将运算符键用红色表示
        for(int i=1;i<=calculate.length/5;i++)
        {
            calculate[i*5-2].setForeground(Color.red);
            calculate[i*5-1].setForeground(Color.red);
        }

        /*初始化三个功能键按钮,将这些键放在一个面板内
         * 布局:网格布局,1行3列。各组件之间的水平竖直间隔都为三个像素*/
        JPanel commandPanel=new JPanel();
        commandPanel.setLayout(new GridLayout(1,3,3,3));
        for(int i=0;i<commands.length;i++)
        {
            commands[i]=new JButton(COMMAND[i]);
            commandPanel.add(commands[i]);
            //将这些键的字体颜色设为红色
            commands[i].setForeground(Color.red);                   
        }

        /*初始化M键按钮,将其放在一个面板内
         * 布局:网格布局,5行1列。各组件之间的水平竖直间隔为3
         * m键字体颜色设为红色*/
        JPanel mPanel=new JPanel();
        mPanel.setLayout(new GridLayout(5,1,3,3));
        for(int i=0;i<M.length;i++)
        {
            m[i]=new JButton(M[i]);
            mPanel.add(m[i]);
            m[i].setForeground(Color.red);
        }
        /*然后进行计算器的整体布局
         * 先将运算操作部分和三个功能键的面板,合为一个面板panel1
         * 布局:边界布局管理器。个组件之间水平竖直间隔都为3个像素
         * 北:commandsPanel,中:calcPanel
         * 
         * */
        JPanel panel1=new JPanel();
        panel1.setLayout(new BorderLayout(3,3));
        panel1.add("North",commandPanel);
        panel1.add("Center",calcPanel);
        /*最后进行这三个面板的整体布局
         * 布局:边界布局
         * west:mPanel,north:commmandPanel,center:panel1*/
        Container c=super.getContentPane();
        c.add("North", resultPanel);
        c.add("West",mPanel);
        c.add("Center",panel1);

        /*为各按钮添加事件侦查器,各按钮使用同一个事件侦查器,即本对象,因为本类implementls ActionListener*/
        for(int i=0;i<commands.length;i++)
        {
            commands[i].addActionListener(this);
        }
        for(int i=0;i<M.length;i++)
        {
            m[i].addActionListener(this);
        }
        for(int i=0;i<calculate.length;i++)
        {
            calculate[i].addActionListener(this);
        }   
    }
        public void actionPerformed(ActionEvent e) {
            //获取事件源的标签
            String label=e.getActionCommand();
            if(label.equals(COMMAND[0]))
            {//用户按了Backspace键
                handleBackspace();
            }
            else if(label.equals(COMMAND[1]))
            {//用户按了CE键, 清除当前输入的数字           
                handleCE();
            }
            else if(label.equals(COMMAND[2]))
            {//用户按了C键,清除之前的所有输入
                resultText.setText("0");
                //result=0;
            }
            else if("0123456789.".indexOf(label)>=0)//String.indexOf(String)返回char在String中的位置
            {//用户按了数字键或小数点
                handleCalcKey(label);
                /*
                if(!operate)
                {
                    result=getNumberFromText();
                }
                */   
            }
            else if(label.equals("="))
            {
                handleEqual();
            }
            else
            {//用户按了=号,这时开始计算,并将结果输出到文本框
                handleOperator(label);  
            }

            //M键涉及到存储器暂不做处理         
        }

        //编写各种按钮的处理事件

        //处理Backspace键被按下的事件
        private void handleBackspace()
        {
            String text=resultText.getText();
            int i=text.length();
            if(i>0)
            {
                //退一格,将文本框中的最后一个字符去掉
                text=text.substring(0,i-1); 
                resultText.setText(text);
            }
            else
            {
                resultText.setText("0");
            }
            /*
            if(!operate)//重新读取退格后文本框中的数据
            {
                result=getNumberFromText();
            }
            */  
        }
        //处理CE键被按下的事件,清除当前输入的数字
        private void handleCE()
        {
            String text=resultText.getText();
            int i=text.length();
            if(i>0)
            {
                //退一格,将文本框中的最后一个字符去掉
                text=text.substring(0,i-1);  
                resultText.setText(text);
            }
            else
            {
                resultText.setText("0");
            }           
        }
        //处理数字键或小数点键被按下的事件
        private void handleCalcKey(String number)
        {
            String tempStr=resultText.getText();    
            if(preferExist)//之前已有数字
            {
                if(number.equals("."))
                {
                    if((tempStr.indexOf("."))<0)//说明之前不存在小数点,并且之前已有数字输入
                    {
                        resultText.setText(tempStr+".");

                    }           
                }
                else
                {
                    resultText.setText(tempStr+number);
                }       
            }
            else//还没输入数字
            {
                resultText.setText(number);
                preferExist=true;
            }
        }

        //如果用户一次计算多个数,连续运算,在两个数运算后其实相当于按了一次=,做了一次计算
        private void calcMore()
        {
            if(operate==true)
            {
                result=beforebefore;
                handleEqual();
            }
        }
        /*处理运算符键被按下的事件,如果是单目运算符直接计算结果,
         * 如果是双目运算符,将用户选择的运算符保存下来,便于输入第二个操作数后进行运算
         */
        private void handleOperator(String operator)
        {
            //前一个数
            result=getNumberFromText();


            if (operator.equals("/"))
            {
                op="/";
                calcMore();
            } 
            else if (operator.equals("1/x"))
            {
                //op="1/x";
                // 倒数运算
                if (result== 0.0) 
                {
                    // 操作不合法
                    resultText.setText("零没有倒数");
                } 
                else 
                {
                    result= 1/result;
                }
            }
            else if (operator.equals("+")) 
            {
                op="+";         
                calcMore();
            }
            else if (operator.equals("-"))
            {
                op="-";
                calcMore();
            } 
            else if (operator.equals("*")) 
            {
                op="*";
                calcMore();
            }
            else if (operator.equals("sqrt")) 
            {
                //op="sqrt";
                // 平方根运算
                result= Math.sqrt(result);
            } 
            else if (operator.equals("%")) 
            {
                //op="%";
                // 百分号运算,除以100
                result= result/ 100;
            } 
            else if (operator.equals("+/-"))
            {
                //op="+/-";
                // 正数负数运算
                result= result*(-1);
            } 
            beforebefore=result;
            preferExist=false;
            operate=true;
        }
        //=.处理双目运算符。根据之前输入的操作符号进行计算,并将结果输出到文本框
        private void handleEqual()
        {
            if(operate)//已经按过操作符
            {
                if (op.equals("/"))
                {
                    // 除法运算
                    // 如果当前结果文本框中的值等于0
                    if (getNumberFromText() == 0.0)
                    {
                        // 操作不合法
                        resultText.setText("除数不能为零");
                    } 
                    else
                    {
                        result/= getNumberFromText();
                    }
                }    
                else if (op.equals("+")) 
                {            
                    // 加法运算
                    result+= getNumberFromText();
                }
                else if (op.equals("-"))
                {
                    // 减法运算
                    result-= getNumberFromText();
                } 
                else if (op.equals("*")) 
                {
                    // 乘法运算
                    result*= getNumberFromText();
                }
            }
            resultText.setText(Double.toString(result));
            operate=false;
            /*
             * 这时不能将之后输入的数字再加到之前的结果后面,若要输入数字,
             * 将之前的输入置为false,重新输入.
             */
            preferExist=false;
        }
        //从文本框中获取第二个操作数
        private double getNumberFromText()
        {
            double number=0;
            if(resultText.getText()!=null)
            {
                number=Double.parseDouble(resultText.getText());

            }
            return number;
        }
     public static void main(String[] args)
     {
         Calculator cal=new Calculator();
         cal.setSize(400,250);
         cal.setVisible(true);
         cal.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     }
}

这里写图片描述
参考代码:http://yuncode.net/code/c_50b0c000f0c2e62实在无法理解双目运算如何在没输入前获取第二个操作数,所以只好自己改写了。
/*之前在这个过程中总是容易让我比较困惑的问题就是:连续计算时,中间值会被当前文本框中的值覆盖问题.
* 于是添加了beforebefore这个变量,档连续计算时作为中间值。
* 例如:连续计算5+3+2
* (1)5+后,result=5,此时operate=true;beforebefore=result=5;
* (2)3+后,result=3,此时会调用calcMore判断是否是连续计算,if(operate==true)
* 说明之前已按过操作符,将beforebefore之前存的值赋给result,result=5;
* 所以利用beforebefore这个中间变量避免了连续计算时上一次的值被新输入的值覆盖,完成连续计算。
*
*/

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值