[Java]基于JFrame的计算器界面及部分功能实现

完成效果预览


程序设计

-布局设计-

整体布局采用BorderLayout,Center为程序主要交互部分,North为菜单界面。

主要界面由两个采用GridLayout分布的子面板组成,两个面板分别显示计算过程和交互按钮。

-主要使用控件-

JLabel:通过标签显示计算式与结果。

JButton:通过按钮实现程序与用户的基本交互。

JPanel:通过面板组建程序图形界面的基本布局。

JMenubar/JMenu/JMenuItem:用于组建菜单。

Font:用于设置字体样式。

-数据结构-

通过数字栈与符号栈完成对算式的计算算法。

通过哈希表建立符号名称到按钮的映射。


代码部分 

程序基本架构

calculator.java

public class calculator {
    public static void main(String[] argv) {
        new app();
    }
}

app.java

import java.awt.*;
import java.awt.event.*;
import java.util.*;

import javax.swing.*;

public class app extends JFrame {

    private static String ex = "";
    private static JLabel expression, res;// 分别存储表达式 计算结果
    private static Stack<Character> sign_stack = new Stack<Character>();// 符号栈
    private static Stack<Double> number_stack = new Stack<Double>();// 数字栈
    private static Double curIndex, totIndex;// 当前数字结果 整个表达式的数字结果
    private static final String buttonName[][] = { { "C", "÷", "×", "Back" }, { "7", "8", "9", "-" },
            { "4", "5", "6", "+" },
            { "1", "2", "3", "√" }, { "%", "0", ".", "=" } };
    private static JButton buttonList[][] = new JButton[5][4];
    private static HashMap<String, JButton> buttonMap = new HashMap<String, JButton>();// 映射 符号->按钮
    private static JMenuItem standardMode, sciMode, appearance, history;
    private static Double unit = 1.0;// 用来记录小数最小单位

    // 计算结果并更新
    private static void calculate() {
        totIndex = 0.0;
        Stack<Character> sstack = (Stack<Character>) sign_stack.clone();
        Stack<Double> nstack = (Stack<Double>) number_stack.clone();
        if (sstack.empty() || sstack.firstElement() != '÷')
            nstack.push(curIndex);
        else {
            sstack.pop();
            sstack.push('×');
            nstack.push(1 / curIndex);
        }
        unit = 1.0;
        while (!sstack.empty()) {
            Character s = sstack.pop();
            if (s == '+') {
                double a = nstack.pop();
                totIndex += a;
            } else if (s == '-') {
                double a = nstack.pop();
                totIndex -= a;
            } else if (s == '×') {
                double a = nstack.pop(), b = nstack.pop();
                nstack.push(a * b);
            } else if (s == '÷') {
                double a = nstack.pop(), b = nstack.pop();
                nstack.push(b / a);
            }
        }
        totIndex += nstack.pop();
    }

    // 数字按键事件
    private static void NumberButtonAction(int n) {
        if (number_stack.size() < sign_stack.size()) {
            number_stack.push(curIndex);
            curIndex = 0.0;
        }
        if (unit.equals(1.0)) {
            curIndex = curIndex * 10 + n;
        } else {
            curIndex += n * unit;
            unit /= 10;
        }
        res.setText(tool.Rounding(Double.toString(curIndex)));
        ex += (char) (n + 48);
        expression.setText(ex);
    }

    // 符号按键事件
    private static void SignButtonAction(char sign) {
        calculate();
        res.setText(tool.Rounding(Double.toString(totIndex)));
        if (sign_stack.empty() || sign_stack.firstElement() != '÷')
            number_stack.push(curIndex);
        else {
            sign_stack.pop();
            sign_stack.push('×');
            number_stack.push(1 / curIndex);
        }
        unit = 1.0;
        curIndex = 0.0;
        sign_stack.push(sign);
        ex += sign;
        expression.setText(ex);
    }

    private static void buttonAction() {

        buttonMap.get("1").addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                NumberButtonAction(1);
            }

        });

        buttonMap.get("2").addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                NumberButtonAction(2);
            }

        });

        buttonMap.get("3").addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                NumberButtonAction(3);
            }

        });

        buttonMap.get("4").addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                NumberButtonAction(4);
            }

        });

        buttonMap.get("5").addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                NumberButtonAction(5);
            }

        });

        buttonMap.get("6").addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                NumberButtonAction(6);
            }

        });

        buttonMap.get("7").addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                NumberButtonAction(7);
            }

        });

        buttonMap.get("8").addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                NumberButtonAction(8);
            }

        });

        buttonMap.get("9").addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                NumberButtonAction(9);
            }

        });

        buttonMap.get("0").addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                NumberButtonAction(0);
            }

        });

        buttonMap.get("C").addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                ex = "";
                expression.setText(ex);
                curIndex = 0.0;
                unit = 1.0;
                res.setText(tool.Rounding(Double.toString(curIndex)));
                sign_stack.clear();
            }

        });

        buttonMap.get("=").addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                calculate();
                number_stack.clear();
                sign_stack.clear();
                res.setText(tool.Rounding(Double.toString(totIndex)));
                number_stack.push(totIndex);
                curIndex = totIndex;
                ex = tool.Rounding(Double.toString(curIndex));
                expression.setText(ex);
            }

        });

        buttonMap.get("+").addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                SignButtonAction('+');
            }

        });

        buttonMap.get("-").addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                SignButtonAction('-');
            }

        });

        buttonMap.get("×").addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                SignButtonAction('×');
            }

        });

        buttonMap.get("÷").addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                SignButtonAction('÷');
            }

        });

        buttonMap.get("Back").addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                if (ex.length() == 0) {
                    return;
                }
                char c = ex.charAt(ex.length() - 1);
                ex = ex.substring(0, ex.length() - 1);
                if (c == '.') {
                    unit = 1.0;
                } else if (!unit.equals(1.0)) {
                    unit *= 10;
                    curIndex -= (c - 48) * unit;
                } else {
                    if (c >= '0' && c <= '9') {
                        curIndex -= c - 48;
                        curIndex /= 10;
                    } else {
                        sign_stack.pop();
                        curIndex = number_stack.pop();
                        unit = tool.getDecimalUnit(curIndex);
                    }
                }
                expression.setText(ex);
                res.setText(tool.Rounding(Double.toString(curIndex)));
            }

        });

        buttonMap.get(".").addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                if (ex.charAt(ex.length() - 1) == '.')// 防止小数点重复输入
                    return;
                ex += '.';
                expression.setText(ex);
                unit /= 10;
            }

        });

    }

    private void UI() {
        this.setLayout(new BorderLayout());

        // 设置字体格式
        Font font = new Font("黑体", Font.PLAIN, 50);
        Font buttonFont = new Font("黑体", Font.PLAIN, 25);
        Font menuFont = new Font("黑体", Font.PLAIN, 12);

        // 菜单
        JMenuBar bar = new JMenuBar();
        JMenu mode = new JMenu("模式");
        mode.setFont(menuFont);
        standardMode = new JMenuItem("标准");
        sciMode = new JMenuItem("科学");
        mode.add(standardMode);
        mode.add(sciMode);
        JMenu func = new JMenu("功能");
        func.setFont(menuFont);
        appearance = new JMenuItem("外观设置");
        history = new JMenuItem("历史记录");
        func.add(appearance);
        func.add(history);
        bar.add(mode);
        bar.add(func);
        this.add("North", bar);

        //总面板
        JPanel panel = new JPanel(new GridLayout(2, 1));

        // 分面板一:计算器显示界面
        JPanel show = new JPanel(new GridLayout(2, 1));
        expression = new JLabel();// 算术表达式
        expression.setFont(font);
        res = new JLabel(tool.Rounding(Double.toString(curIndex)));// 计算结果
        res.setFont(new Font("黑体", Font.PLAIN, 35));
        show.add(expression);
        show.add(res);

        // 分面板二:计算机按键
        JPanel buttonPanel = new JPanel(new GridLayout(5, 4));
        for (int i = 0; i < 5; i++) {
            for (int j = 0; j < 4; j++) {
                buttonList[i][j] = new JButton(buttonName[i][j]);
                buttonMap.put(buttonName[i][j], buttonList[i][j]);
                if (buttonName[i][j].equals("Back"))
                    buttonList[i][j].setFont(new Font("黑体", Font.PLAIN, 20));
                else
                    buttonList[i][j].setFont(buttonFont);
                if (buttonName[i][j].equals("="))
                    buttonList[i][j].setBackground(new Color(65, 105, 225));
                else if (i >= 1 && j <= 2)
                    buttonList[i][j].setBackground(Color.white);
                buttonPanel.add(buttonList[i][j]);
            }
        }

        panel.add(show);
        panel.add(buttonPanel);
        this.add(panel);

        //JFrame基本设置
        this.setVisible(true);
        this.setBounds(400, 150, 390, 550);
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
        this.setTitle("烨的计算器");
    }

    app() {
        curIndex = 0.0;
        totIndex = 0.0;
        UI();
        buttonAction();
    }

}

tool.java

public abstract class tool {

    // 省略小数末尾的0
    public static String Rounding(String s) {
        if (s.lastIndexOf('.', s.length() - 1) == -1) {
            return s;
        }
        int i = s.length() - 1;
        for (; i >= 0; i--) {
            if (s.charAt(i) == '.')
                break;
            if (s.charAt(i) != '0') {
                return s.substring(0, i + 1);
            }
        }
        return s.substring(0, i);
    }

    // 获取最小小数单位
    public static Double getDecimalUnit(Double n) {
        String s = Double.toString(n);
        if (s.indexOf('.') == -1) {
            return 1.0;
        }
        return Math.pow(0.1, s.length() - s.indexOf('.'));
    }
}
  • 10
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值