Java realizes imitation win10 calculator - micro-upgrade version

The following code is to cope with this semester's Java end-of-term homework. By referring to the blogger Henry_626 's code , I use Java to implement the imitation win10 calculator. Compared with the first generation version of Henry_626, some details are added to win10 Calculator reduction degree, such as increasing the text display of the calculation process, the processing of decimal places and other details; and on the basis of the requirements of the big homework, adding cos sin exponential operation and factorial operation

The picture on the right shows the comparison of win10 calculator

insert image description here

package demo1;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DecimalFormat;
import java.math.BigInteger;
//时间允许,可通过引入一下包,实现鼠标滑过按钮变色和键盘输入
//import java.awt.event.MouseAdapter;
//import java.awt.event.MouseEvent;
//import java.awt.event.KeyAdapter;
//import java.awt.event.KeyEvent;
import java.math.BigDecimal;//控制小数点后几位

public class Calculator implements ActionListener {
    
    

    private JFrame frame = new JFrame();//界面应用程序,窗口

    //计算器上各按键的符号
    private String[] keys = {
    
    "%", "CE", "C", "←", "n!", "aⁿ", "cos", "sin", "1⁄x", "x²", "√x", "÷", "7", "8", "9",
            "×", "4", "5", "6", "-", "1", "2", "3", "+", "+/-", "0", ".", "="};
    private JButton button[] = new JButton[keys.length];  //计算器上按键的按钮(数组保存)
    private JTextField resultText = new JTextField("0");//显示计算结果文本框
    private JTextField processText = new JTextField();//显示计算过程文本框
    private boolean firstDigit = true;  // 标志用户按的是否是整个表达式的第一个数字,或者是运算符后的第一个数字
    private double resultNum = 0.0000;   // 计算的中间结果
    private String operator = "=";   // 当前运算的运算符(按键"C"时需要将其还原为"=")
    private boolean operateValidFlag = true;   // 判断操作是否合法

    char charA;

    public Calculator() {
    
    //本类Calculator的构造函数
        init();  // 初始化计算器

        frame.setTitle("计算器(纯原版)");
        frame.setSize(350, 550);
        frame.setLocation(500, 300);
        frame.setResizable(true);  // 允许修改计算器窗口的大小
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//点击关闭按钮后执行exit退出应用程序
    }


    private void init() {
    
    //初始化变量,创建面板,添加按钮,面板布局
        Color color1 = new Color(181, 181, 181);
        Color color2 = new Color(126, 192, 238);  //等于号专属颜色
        Color color3 = new Color(232, 232, 232);  //背景颜色//功能键和运算符颜色
        //Color color4 = new Color(132, 132, 232);//紫色

        JPanel resultTextPanel = new JPanel();// 建立一个画板放文本框
        resultTextPanel.setLayout(new BorderLayout());
        resultTextPanel.setSize(400, 50);
        resultTextPanel.add(resultText);
        resultText.setFont(new Font("黑体", Font.BOLD, 55));  //设置文本框中文字的字体以及大小,加粗
        resultText.setHorizontalAlignment(JTextField.RIGHT);  //文本框中的内容采用右对齐方式
        resultText.setEditable(false);  //不能修改结果文本框
        resultText.setBorder(null);  //删除文本框的边框
        resultText.setBackground(color1);// 设置文本框背景颜色

        JPanel processTextPanel = new JPanel();
        processTextPanel.setLayout(new BorderLayout());
        processTextPanel.setSize(400, 50);
        processTextPanel.add(processText);
        processText.setFont(new Font("黑体", Font.PLAIN, 25));  //设置文本框中文字的字体以及大小,加粗
        processText.setHorizontalAlignment(JTextField.RIGHT);  //文本框中的内容采用右对齐方式
        processText.setEditable(false);  //不能修改结果文本框
        processText.setBorder(null);  //删除文本框的边框

        processText.setBackground(color1);

        // 初始化计算器上键的按钮,将键放在一个画板内
        JPanel keysPanel = new JPanel();
        // 用网格布局器,6行,4列的网格,网格之间的水平方向垂直方向间隔均为2个像素
        keysPanel.setLayout(new GridLayout(7, 4, 2, 2));

        //初始化功能按钮
        for (int i = 0; i < 12; i++) {
    
    
            button[i] = new JButton(keys[i]);
            Dimension preferredSize = new Dimension(95, 50);
            button[i].setPreferredSize(preferredSize);
            keysPanel.add(button[i]);
            button[i].setBackground(color3);
            button[i].setForeground(Color.black);//设置字体颜色
            button[i].setFont(new Font(Font.SERIF, Font.PLAIN, 18));
            if (i == 11 || i == 3) button[i].setFont(new Font(Font.SERIF, Font.PLAIN, 30));
            if (i == 1 || i == 2) button[i].setFont(new Font("黑体", Font.PLAIN, 18));
            button[i].setBorderPainted(false);  //去除按钮的边框
        }

        //初始化运算符及数字键按钮
        for (int i = 12; i < keys.length; i++) {
    
    
            button[i] = new JButton(keys[i]);
            Dimension preferredSize = new Dimension(95, 50);
            button[i].setPreferredSize(preferredSize);
            keysPanel.add(button[i]);
            if ((i + 1) % 4 == 0) {
    
    
                button[i].setBackground(color3);//运算符按钮
                button[i].setFont(new Font(Font.SERIF, Font.PLAIN, 30));
            } else {
    
    
                button[i].setBackground(Color.white);//数字按钮
                button[i].setFont(new Font("黑体", Font.BOLD, 20));
            }
            if (i == 19) button[i].setFont(new Font(Font.SERIF, Font.PLAIN, 18));
            button[i].setForeground(Color.black);

            button[i].setBorderPainted(false);  //去除按钮的边框
        }
        button[27].setBackground(color2);  // 用浅蓝色 覆盖更改 标记'='

        keysPanel.setBackground(color1);

        //将文本框所在的面板放在北部和中部,将keysPanel面板放在计算器的南部
        frame.getContentPane().add("North", processTextPanel);
        frame.getContentPane().add("Center", resultTextPanel);
        frame.getContentPane().add("South", keysPanel);
        processTextPanel.setBorder(BorderFactory.createMatteBorder(25, 3, 0, 3, color1));
        resultTextPanel.setBorder(BorderFactory.createMatteBorder(0, 3, 5, 3, color1));
        keysPanel.setBorder(BorderFactory.createMatteBorder(5, 3, 5, 3, color1));

        for (int i = 0; i < keys.length; i++) {
    
    
            button[i].addActionListener(this);// 为各按钮添加事件监听器,都使用同一个事件监听器。
        }
    }

    public void actionPerformed(ActionEvent ev) {
    
    //监听函数,将得到的事件选择对应的函数

        String command = ev.getActionCommand();  // 获取事件源

        if (command.equals(keys[3])) doBackspace();// 用户按了"Back"键
        else if (command.equals(keys[1])) resultText.setText("0");// 用户按了"CE"键
        else if (command.equals(keys[2])) doC();// 用户按了"C"键
        else if ("0123456789.".indexOf(command) >= 0) doNumber(command);// 用户按了数字键或者小数点键
        else if (command.equals(keys[0]) || command.equals(keys[4]) || command.equals(keys[6])
                || command.equals(keys[7]) || command.equals(keys[8]) || command.equals(keys[9])
                || command.equals(keys[10]) || command.equals(keys[24])) doOperator1(command);
            // 用户按了只需一个数的运算键(求倒数,%,开方,平方,取正负数)
        else doOperator2(command);
    }


    private void doBackspace() {
    
    //删除键
        String text = resultText.getText();
        int i = text.length();
        if (i > 0) {
    
    
            text = text.substring(0, i - 1);  // 退格,将文本最后一个字符去掉
            if (text.length() == 0) {
    
    
                resultText.setText("0");// 如果文本没有内容了,则初始化计算器的各种值
                firstDigit = true;
                operator = "=";
            } else {
    
    
                resultText.setText(text);// 显示新的文本
            }
        }
    }

    private void doC() {
    
    //清除键
        // 初始化计算器的各种值
        processText.setText(null);
        resultText.setText("0");
        firstDigit = true;
        operator = "=";
    }

    private void doNumber(String key) {
    
    //得到数字,处理数字
        if (firstDigit) {
    
    
            // 输入的为第一个数
            resultText.setText(null);
            resultText.setText(key);

        } else if ((key.equals(".")) && (resultText.getText().indexOf(".") < 0)) {
    
    
            //indexOf() 返回指定字符在字符串中第一次出现处的索引,如果此字符串中没有这样的字符,则返回 -1
            // 输入的是小数点,并且之前没有小数点,则将小数点附在结果文本框的后面
            resultText.setText(resultText.getText() + ".");
        } else if (!key.equals(".")) {
    
     // 如果输入的不是小数点,则将数字附在结果文本框的后面
            resultText.setText(resultText.getText() + key);
        }
        firstDigit = false;
    }


    private void doOperator1(String key) {
    
    //进行单目运算
        operator = key;  // 运算符为用户按的按钮
        if (operator.equals("1⁄x")) {
    
    // 倒数运算
            if (resultNum == 0) {
    
    
                operateValidFlag = false;  //操作不合法
                resultText.setText("除数不能为零");
            } else {
    
    
                resultNum = 1 / getNumberFromText();
                processText.setText("1/(" + resultText.getText() + ")");
            }
        } else if (operator.equals("√x")) {
    
    // 平方根运算
            if (resultNum < 0) {
    
    
                operateValidFlag = false;  //操作不合法
                resultText.setText("无效输入");
            } else {
    
    
                resultNum = Math.sqrt(getNumberFromText());
                processText.setText("√(" + resultText.getText() + ")");
                //resultNum = getNumberFromText();

            }
        } else if (operator.equals("x²")) {
    
    // 平方运算X
            resultNum = getNumberFromText() * getNumberFromText();
            processText.setText("sqr(" + resultText.getText() + ")");
        } else if (operator.equals("%")) {
    
    // 百分号运算,除以100
            resultNum = getNumberFromText() / 100;
        } else if (operator.equals("n!")) {
    
    
            BigInteger num = new BigInteger("1");
            BigInteger flat = new BigInteger("1");
            for (int i = 0; i < getNumberFromText(); i++) {
    
    
                flat = flat.multiply(num);
                num = num.add(new BigInteger("1"));
            }
            resultNum = flat.floatValue();//BigInteger转换为float
            processText.setText("fact(" + resultText.getText() + ")");
        } else if (operator.equals("cos")) {
    
    
            resultNum = Math.cos(getNumberFromText());
            processText.setText("cos(" + resultText.getText() + ")");
        } else if (operator.equals("sin")) {
    
    
            resultNum = Math.sin(getNumberFromText());
            processText.setText("sin(" + resultText.getText() + ")");
        } else if (operator.equals("+/-")) {
    
    // 正数负数运算
            resultNum = getNumberFromText() * (-1);
        }
        isOperateValidFlag(operateValidFlag);
        firstDigit = true;//复位
        if (operateValidFlag == false) processText.setText(null);
        operateValidFlag = true;
    }


    private void doOperator2(String key) {
    
    //进行双目运算
        if (operator.equals("÷")) {
    
    // 除法运算// 如果当前结果文本框中的值等于0
            if (getNumberFromText() == 0.0) {
    
    
                operateValidFlag = false;  //操作不合法
                //resultText.setFont(new Font("黑体", Font.BOLD, 40));
                resultText.setText("除数不能为零");
                //resultText.setFont(new Font("黑体", Font.BOLD, 55));
            } else {
    
    
                resultNum /= getNumberFromText();
            }
        } else if (operator.equals("+")) {
    
    // 加法运算
            resultNum += getNumberFromText();
        } else if (operator.equals("-")) {
    
    // 减法运算
            resultNum -= getNumberFromText();
        } else if (operator.equals("×")) {
    
    // 乘法运算
            resultNum *= getNumberFromText();
        } else if (operator.equals("=")) {
    
    // 赋值运算
            resultNum = getNumberFromText();
            processText.setText(null);
        } else if (operator.equals("aⁿ")) {
    
    
            resultNum = Math.pow(resultNum, getNumberFromText());
        }

        if (key.equals("+") || key.equals("×") || key.equals("÷") || key.equals("=")) {
    
    
            processText.setText(processText.getText() + resultText.getText() + key);
        } else if (key.equals("-")) {
    
    
            processText.setText(processText.getText() + resultText.getText() + "-");
        } else if (key.equals("aⁿ")) {
    
    
            processText.setText(processText.getText() + resultText.getText() + "^");

        }

        isOperateValidFlag(operateValidFlag);
        operator = key;  // 运算符为用户按的按钮
        firstDigit = true;
        if (operateValidFlag == false) {
    
    
            processText.setText(null);
        }
        operateValidFlag = true;
    }

    private void isOperateValidFlag(boolean operateValidFlag) {
    
    
        if (operateValidFlag) {
    
    // 操作合法的情况下,将小数点后的位数进行处理
            long t1 = (long) resultNum;
            double t2 = resultNum - t1;//得到小数部分
            BigDecimal bd = new BigDecimal(String.valueOf(resultNum));//得到小数位数
            if (t2 == 0) {
    
    
                resultText.setText(String.valueOf(t1));//转化为字符串
            } else if (bd.scale() == 1) {
    
    
                resultText.setText(String.valueOf(new DecimalFormat("0.0").format(resultNum)));
            } else if (bd.scale() == 2) {
    
    
                resultText.setText(String.valueOf(new DecimalFormat("0.00").format(resultNum)));
            } else if (bd.scale() == 3) {
    
    
                resultText.setText(String.valueOf(new DecimalFormat("0.000").format(resultNum)));
            } else if (bd.scale() == 4) {
    
    
                resultText.setText(String.valueOf(new DecimalFormat("0.0000").format(resultNum)));
            } else if (bd.scale() == 5) {
    
    
                resultText.setText(String.valueOf(new DecimalFormat("0.00000").format(resultNum)));
            } else if (bd.scale() == 6) {
    
    
                resultText.setText(String.valueOf(new DecimalFormat("0.000000").format(resultNum)));
            } else if (bd.scale() == 7) {
    
    
                resultText.setText(String.valueOf(new DecimalFormat("0.0000000").format(resultNum)));
            } else if (bd.scale() == 8) {
    
    
                resultText.setText(String.valueOf(new DecimalFormat("0.00000000").format(resultNum)));
            } else {
    
    
                resultText.setText(String.valueOf(new DecimalFormat("0.000000000").format(resultNum)));
            }
        }
    }

    private double getNumberFromText() {
    
    
        double result = 0;
        try {
    
    
            result = Double.valueOf(resultText.getText()).doubleValue();
        } catch (NumberFormatException e) {
    
    
        }
        return result;
    }

    public static void main(String[] args) {
    
    
        new Calculator();
    }

}

When calculating 1.2+2.2, due to the principle of binary storage, the answer will be equal to 3.4000000000000004, which is a normal situation. Currently, the ability is limited, and I don’t know how to solve this problem

Interested partners are welcome to iteratively update and optimize this calculator. Our goal is to highly restore the win10 calculator!

Guess you like

Origin blog.csdn.net/weixin_51625354/article/details/122211758