java-swing编程,实现计算器——支持四则运算

摘自:Ecqiao

package cal;

import java.awt.Color;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextArea;


public class CalFrame extends JFrame {
    
    //配色
    private final static Color OP_COLOR = new Color(251, 150, 110);
    private final static Color NUM_COLOR = new Color(36, 147, 190);
    private final static Color EQUAL_COLOR = new Color(239, 187, 36);
    private final static Color CLR_COLOR = new Color(50, 252, 75);
    private final static Color DEL_COLOR = new Color(0, 152, 120);
    
    private final static Font FONT1 = new Font("黑体", Font.BOLD, 20);
    private final static Font FONT2 = new Font("微软雅黑", Font.PLAIN, 20);
    private final static Font FONT3 = new Font("微软雅黑", Font.PLAIN, 15);
    
    private JButton num0 = new JButton("0");
    private JButton num1 = new JButton("1");
    private JButton num2 = new JButton("2");
    private JButton num3 = new JButton("3");
    private JButton num4 = new JButton("4");
    private JButton num5 = new JButton("5");
    private JButton num6 = new JButton("6");
    private JButton num7 = new JButton("7");
    private JButton num8 = new JButton("8");
    private JButton num9 = new JButton("9");
    private JButton decimalPoint = new JButton(".");
    private JButton addButton = new JButton("+");
    private JButton minusButton = new JButton("-");
    private JButton mulButton = new JButton("X");
    private JButton divButton = new JButton("÷");
    private JButton equalButton = new JButton("=");
    private JButton leftBracket = new JButton("(");
    private JButton rightBracket = new JButton(")");
    private JButton clearButton = new JButton("Clear");
    private JButton deleteButton = new JButton("Del");
    
    private JLabel equationLabel = new JLabel("算式");
    private JLabel resultLabel = new JLabel("结果");
    private JTextArea equation = new JTextArea(2,30);
    private JTextArea result = new JTextArea(1,30);

    private JPanel jp1 = new JPanel();
    private JPanel jp2 = new JPanel();

    public CalFrame () {

        equation.setEditable(false);
        result.setEditable(false);
        
        //颜色,字体设置
        colorAndFontSettings();
        
        //添加动作
        actionSettings();
        
        //设置各个组成部分的位置
        positionSettings();
        
        //其他设置
        setLayout( new GridLayout(2,1));
        add(jp1);
        add(jp2);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setResizable(false);
        setTitle("QiaoCalculator v2.3");
        setSize(500, 400);
        setLocation(200, 200);
        setVisible(true);
        
    }
    
    public static void main ( String[] args ) {
        new CalFrame();
    }
    
    private void colorAndFontSettings () {
        
        equationLabel.setFont(FONT2);
        resultLabel.setFont(FONT2);
        equation.setFont(FONT3);
        result.setFont(FONT3);
        
        num0.setBackground(NUM_COLOR);
        num1.setBackground(NUM_COLOR);
        num2.setBackground(NUM_COLOR);
        num3.setBackground(NUM_COLOR);
        num4.setBackground(NUM_COLOR);
        num5.setBackground(NUM_COLOR);
        num6.setBackground(NUM_COLOR);
        num7.setBackground(NUM_COLOR);
        num8.setBackground(NUM_COLOR);
        num9.setBackground(NUM_COLOR);
        decimalPoint.setBackground(NUM_COLOR);
        
        addButton.setBackground(OP_COLOR);
        addButton.setFont(FONT1);
        minusButton.setBackground(OP_COLOR);
        minusButton.setFont(FONT1);
        mulButton.setBackground(OP_COLOR);
        mulButton.setFont(FONT1);
        divButton.setBackground(OP_COLOR);
        divButton.setFont(FONT1);
        leftBracket.setBackground(OP_COLOR);
        leftBracket.setFont(FONT1);
        rightBracket.setBackground(OP_COLOR);
        rightBracket.setFont(FONT1);
        equalButton.setBackground(EQUAL_COLOR);
        equalButton.setFont(FONT1);
        clearButton.setBackground(CLR_COLOR);
        deleteButton.setBackground(DEL_COLOR);
    }
    
    private void actionSettings () {
        
        num0.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                equation.setText(equation.getText() + "0");
            }
        });
        num1.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                equation.setText(equation.getText() + "1");
            }
        });
        num2.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                equation.setText(equation.getText() + "2");
            }
        });
        num3.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                equation.setText(equation.getText() + "3");
            }
        });
        num4.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                equation.setText(equation.getText() + "4");
            }
        });
        num5.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                equation.setText(equation.getText() + "5");
            }
        });
        num6.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                equation.setText(equation.getText() + "6");
            }
        });
        num7.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                equation.setText(equation.getText() + "7");
            }
        });
        num8.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                equation.setText(equation.getText() + "8");
            }
        });
        num9.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                equation.setText(equation.getText() + "9");
            }
        });
        decimalPoint.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                equation.setText(equation.getText() + ".");
            }
        });
        addButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                equation.setText(equation.getText() + "+");
            }
        });
        minusButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                equation.setText(equation.getText() + "-");
            }
        });
        mulButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                equation.setText(equation.getText() + "X");
            }
        });
        divButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                equation.setText(equation.getText() + "÷");
            }
        });
        leftBracket.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                equation.setText(equation.getText() + "(");
            }
        });
        rightBracket.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                equation.setText(equation.getText() + ")");
            }
        });
        equalButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                
                String cmd = equation.getText();
                Calculate cl = new Calculate();
                
                String resultMsg = cl.calResult(cmd);
                if ( resultMsg.equals("算式格式错误") || resultMsg.equals("除数不能为0") ) {
                    JOptionPane.showMessageDialog(null, resultMsg, "错误", JOptionPane.WARNING_MESSAGE);
                }
                else {
                    result.setText(resultMsg);
                }

            }
        });
        clearButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                equation.setText("");
                result.setText("");
            }
        });
        deleteButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                if( !( equation.getText().equals("")) ) {
                    StringBuffer sb = new StringBuffer();
                    sb.append(equation.getText());
                    sb.delete(sb.length()-1 , sb.length());
                    equation.setText(sb.toString());
                }
            }
        });
        
    }
    
    private void positionSettings () {
        
        jp1.add(equationLabel);
        jp1.add(equation);
        jp1.add(resultLabel);
        jp1.add(result);
        equationLabel.setBounds(0, 0, 50, 30);
        equationLabel.setLocation(0, 0);
        equation.setBounds(50, 0, 150, 30);
        equation.setLocation(50, 0);
        resultLabel.setBounds(0, 30, 50, 30);
        resultLabel.setLocation(0, 30);
        result.setBounds(50, 30, 150, 30);
        result.setLocation(50, 30);

        jp2.setLayout(new GridLayout(4, 5));
        // line-1
        jp2.add(num7);
        jp2.add(num8);
        jp2.add(num9);
        jp2.add(addButton);
        jp2.add(leftBracket);
        // line-2
        jp2.add(num4);
        jp2.add(num5);
        jp2.add(num6);
        jp2.add(minusButton);
        jp2.add(rightBracket);
        // line-3
        jp2.add(num1);
        jp2.add(num2);
        jp2.add(num3);
        jp2.add(mulButton);
        jp2.add(clearButton);
        // line-4
        jp2.add(num0);
        jp2.add(decimalPoint);
        jp2.add(equalButton);
        jp2.add(divButton);
        jp2.add(deleteButton);
        
        jp1.setLocation(0, 0);
        jp1.setVisible(true);
        jp2.setLocation(0, 100);
        jp2.setVisible(true);
        
    }
    
}

 


package cal;


import java.util.Stack;

public class Calculate {
    
    private Stack<Double> numStack = new Stack<Double>();
    private Stack<Character> sybStack = new Stack<Character>(); 
    
    public String calResult ( String equation ) {
        
        //替换乘除号
        equation = equation.replace("X", "*");
        equation = equation.replace("÷", "/");
        
        //处理负号
        equation = negativeNumTransfer(equation);
        
        if ( !checkFormat(equation) ) {
            return "算式格式错误";
        }
        
        equation += "#";
        StringBuffer tempNum = new StringBuffer();
        StringBuffer exp = new StringBuffer().append(equation);
        
        while ( exp.length() != 0 ) {
            
            String temp = exp.substring(0,1);
            exp.delete(0, 1);
            
            if( isNum(temp) )  { // temp是数字
                tempNum.append(temp);
            }
            else { // temp不是数字
                
                if (!"".equals(tempNum.toString())) {
                    // 当表达式的第一个符号为括号
                    double num = Double.parseDouble(tempNum.toString());
                    numStack.push(num);
                    tempNum.delete(0, tempNum.length());
                }
                // 用当前取得的运算符与栈顶运算符比较优先级:若高于,则因为会先运算,放入栈顶;若等于,因为出现在后面,
                // 所以会后计算,所以栈顶元素出栈,取出操作数运算;若小于,则同理,取出栈顶元素运算,将结果入操作数栈。

                // 判断当前运算符与栈顶元素优先级,取出元素,进行计算(因为优先级可能小于栈顶元素,还小于第二个元素等等,需要用循环判断)
                while ( !compare(temp.charAt(0)) && (!sybStack.empty()) ) {
                    double a = numStack.pop();
                    double b = numStack.pop();
                    char ope = sybStack.pop();
                    
                    // 进行简单的计算
                    if( simpleCal(ope, a, b) == false ) {
                        return "除数不能为0";
                    }
                    
                }
                
                // 判断当前运算符与栈顶元素优先级, 如果高,或者低于平,计算完后,将当前操作符号,放入操作符栈
                refreshSybStack(temp);
                
            }
            
        }
        
        return getResultStr(numStack.pop());
    }
    
    private void refreshSybStack ( String temp) {
        if (temp.charAt(0) != '#') {
            sybStack.push(new Character(temp.charAt(0)));
            if (temp.charAt(0) == ')') {// 当栈顶为'(',而当前元素为')'时,则是括号内以算完,去掉括号
                sybStack.pop();
                sybStack.pop();
            }
        }
    } 
    
    private boolean simpleCal ( char ope, double a, double b ) {
        
        double result = 0;
        
        switch (ope) {
        case '+':
            result = b + a;
            numStack.push(result);
            break;
        case '-':
            result = b - a;
            numStack.push(result);
            break;
        case '*':
            result = b * a;
            numStack.push(result);
            break;
        case '/':
            
            if ( a == 0.0 ) {
                return false;
            }
            else {
                result = b / a;
                numStack.push(result);
                break;
            }
            
        }
        
        return true;
    }
    
    private String negativeNumTransfer( String equation ) {
        // 处理算式,将表示负数的部分进行改动,转成calResult方法支持的 
        
        if( equation.length() <= 1 ) {
            return equation;
        }
        
        StringBuffer str = new StringBuffer().append(equation);
        
        for ( int i = 0; i < str.length()-1; ++i ) {
            
            if( !str.substring(i, i+1).equals("-") ) {
                continue;
            }
            
            if ( i == 0 ) {
                char temp = str.charAt(1);
                if( isNumChar(temp) || isDecimalPoint(temp) || isLeftBracket(temp) ) {
                    str.insert(0, "0");
                    i++;
                }
            }
            else {
                char last = str.charAt(i-1);
                char next = str.charAt(i+1);
                
                if( isLeftBracket(last) &&
                    ( isNumChar(next) || isDecimalPoint(next) || isLeftBracket(next) ) ) {
                    str.insert(i, "0");
                    i++;
                }
            }
        }
                
        
        return str.toString();
    }
    
    
    
    private boolean checkFormat ( String equation ) {
        char[] c = equation.toCharArray();
        int singleBracket = 0;
        
        for( int i = 0; i < c.length; ++i ) {
            
            if( isLeftBracket(c[i]) ) {
                singleBracket++;
            }
            if ( isRightBracket(c[i]) ) {
                singleBracket--;
            }
            
            if ( i == 0 ) { //第1个元素只能是[0-9]或者是左括号
                if( !isLeftBracket(c[i]) && !isNumChar(c[i]) ) {
                    return false;
                }
            }
            else if ( isNumChar(c[i]) || isDecimalPoint(c[i]) ) { //数字左边不能是右括号
                if ( isRightBracket(c[i-1]) ) {
                    return false;
                }
            }
            else if( isLeftBracket(c[i]) )  { // 左括号的左边不能是数字和右括号
                if ( isNumChar(c[i-1]) || isDecimalPoint(c[i-1]) || isRightBracket(c[i-1]) ) {
                    return false;
                }
            }
            else {  // 右括号和四则运算符的左边只能是数字或者右括号
                if ( !isNumChar(c[i-1]) && !isRightBracket(c[i-1]) ) {
                    return false;
                }
            }
            
        }
        
        return singleBracket == 0;
    }

    private static boolean isNum ( String temp ) {
        return temp.matches("[0-9]") || temp.equals(".");
    }
    
    private static boolean isLeftBracket ( char c ) {
        return c == '(';
    }
    
    private static boolean isRightBracket ( char c ) {
        return c == ')';
    }
    
    private static boolean isDecimalPoint ( char c ) {
        return c == '.';
    }
    
    private static boolean isNumChar ( char c ) {
        return ( c >= '0' && c <= '9' );
    }

    private boolean compare (char str) {
        if ( sybStack.empty() ) {
            // 当为空时,显然 当前优先级最低,返回高
            return true;
        }
        char last = (char) sybStack.lastElement();
        // 如果栈顶为'('显然,优先级最低,')'不可能为栈顶。
        if (last == '(') {
            return true;
        }
        switch (str) {
        case '#':
            return false;// 结束符
        case '(':
            // '('优先级最高,显然返回true
            return true;
        case ')':
            // ')'优先级最低,
            return false;
        case '*': {
            // '*/'优先级只比'+-'高
            if (last == '+' || last == '-')
                return true;
            else
                return false;
        }
        case '/': {
            if (last == '+' || last == '-')
                return true;
            else
                return false;
        }
        // '+-'为最低,一直返回false
        case '+':
            return false;
        case '-':
            return false;
        }
        return true;
    }
    
    private String getResultStr ( double result ) {
        StringBuffer s = new StringBuffer().append( result + "" );
        
        if ( s.substring(s.length() - 2).equals(".0") ) {
            s.delete( s.length()-2 , s.length() );
        }
        
        return s.toString();
    }
    
}

 


posted @ 2018-05-24 18:39  dafengchui  阅读(2058)  评论(0编辑  收藏  举报