项目一源代码

package shixi;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingConstants;

public class Calculator implements ActionListener {
    private JFrame f;
    private JPanel p;
    //定义两个文本框用来显示算式和结果
    private JTextField show, showexp;
    //定义数字按钮
    private JButton zero, one, two, three, four, five, six, seven, eight, nine;
    //定义控制按钮
    private JButton H, C, DEL, point, LK, RK;
    //定义运算符号按钮
    private JButton div, mul, sum, minus, eql;
    //定义算式的字符串表示
    private String input, output;

    public static void main(String[] args) {
        Calculator c = new Calculator();
        c.display();
    }

    //在构造函数中 初始化控件和变量
    Calculator() {
        f = new JFrame("Calculator By Lny");
        Image image = new ImageIcon("C:\\Users\\李宁宇\\Pictures\\Saved Pictures\\1.jpg").getImage(); //添加背景图片

        p = new BackgroundPanel(image);

        show = new JTextField("0");//创建单行文本控件
        showexp = new JTextField();
        zero = new JButton("0");//创建按钮
        one = new JButton("1");
        two = new JButton("2");
        three = new JButton("3");
        four = new JButton("4");
        five = new JButton("5");
        six = new JButton("6");
        seven = new JButton("7");
        eight = new JButton("8");
        nine = new JButton("9");
        H = new JButton("HIS");
        C = new JButton("C");
        DEL = new JButton("DEL");
        sum = new JButton("+");
        minus = new JButton("-");
        mul = new JButton("*");
        div = new JButton("/");
        point = new JButton(".");
        LK = new JButton("(");
        RK = new JButton(")");
        eql = new JButton("=");
        input = output = "";//初始设置存储算式和结果的字符串为空串
    }

    //计算器界面设置
    public void display() {
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//设置关闭就退出程序

        //设置显示结果的单行文本框相关属性
        show.setFont(new Font(Font.SERIF, Font.BOLD, 40));//设置字体样式
        show.setBorder(BorderFactory.createEmptyBorder());//设置单行文本控件无边框
        show.setHorizontalAlignment(SwingConstants.RIGHT);//设置文本靠右显示
        show.setEnabled(false);//设置单行文本框不能点击

        showexp.setFont(new Font(Font.SERIF, Font.BOLD, 16));//设置字体样式
        showexp.setBorder(BorderFactory.createEmptyBorder());//设置单行文本控件无边框
        showexp.setHorizontalAlignment(SwingConstants.RIGHT);//设置文本靠右显示
        showexp.setEnabled(false);//设置文本框不能点击

        H.setForeground(Color.red);//设置按钮字体颜色为蓝色
        H.setFont(new Font(Font.SERIF, Font.BOLD, 16));//设置按钮字体样式
        H.setContentAreaFilled(false);//设置按钮为透明效果

        C.setForeground(Color.red);
        C.setFont(new Font(Font.SERIF, Font.BOLD, 16));
        C.setContentAreaFilled(false);

        DEL.setForeground(Color.red);
        DEL.setFont(new Font(Font.SERIF, Font.BOLD, 16));
        DEL.setContentAreaFilled(false);

        LK.setForeground(Color.red);//设置按钮字体颜色为蓝色
        LK.setFont(new Font(Font.SERIF, Font.BOLD, 16));//设置按钮字体样式
        LK.setContentAreaFilled(false);//设置按钮为透明效果

        RK.setForeground(Color.red);//设置按钮字体颜色为蓝色
        RK.setFont(new Font(Font.SERIF, Font.BOLD, 16));//设置按钮字体样式
        RK.setContentAreaFilled(false);//设置按钮为透明效果

        sum.setForeground(Color.BLUE);
        sum.setFont(new Font(Font.SERIF, Font.BOLD, 16));
        sum.setContentAreaFilled(false);

        minus.setForeground(Color.BLUE);
        minus.setFont(new Font(Font.SERIF, Font.BOLD, 16));
        minus.setContentAreaFilled(false);

        mul.setFont(new Font(Font.SERIF, Font.BOLD, 16));
        mul.setForeground(Color.BLUE);
        mul.setContentAreaFilled(false);

        div.setForeground(Color.BLUE);
        div.setFont(new Font(Font.SERIF, Font.BOLD, 16));
        div.setContentAreaFilled(false);

        point.setForeground(Color.BLUE);
        point.setFont(new Font(Font.SERIF, Font.BOLD, 16));
        point.setContentAreaFilled(false);

        eql.setForeground(Color.red);
        eql.setFont(new Font(Font.SERIF, Font.BOLD, 16));
        eql.setContentAreaFilled(false);

        zero.setForeground(Color.BLUE);
        zero.setFont(new Font(Font.SERIF, Font.BOLD, 16));
        zero.setContentAreaFilled(false);

        one.setForeground(Color.BLUE);
        one.setFont(new Font(Font.SERIF, Font.BOLD, 16));
        one.setContentAreaFilled(false);

        two.setForeground(Color.BLUE);
        two.setFont(new Font(Font.SERIF, Font.BOLD, 16));
        two.setContentAreaFilled(false);

        three.setForeground(Color.BLUE);
        three.setFont(new Font(Font.SERIF, Font.BOLD, 16));
        three.setContentAreaFilled(false);

        four.setForeground(Color.BLUE);
        four.setFont(new Font(Font.SERIF, Font.BOLD, 16));
        four.setContentAreaFilled(false);

        five.setForeground(Color.BLUE);
        five.setFont(new Font(Font.SERIF, Font.BOLD, 16));
        five.setContentAreaFilled(false);

        six.setForeground(Color.BLUE);
        six.setFont(new Font(Font.SERIF, Font.BOLD, 16));
        six.setContentAreaFilled(false);

        seven.setForeground(Color.BLUE);
        seven.setFont(new Font(Font.SERIF, Font.BOLD, 16));
        seven.setContentAreaFilled(false);

        eight.setForeground(Color.BLUE);
        eight.setFont(new Font(Font.SERIF, Font.BOLD, 16));
        eight.setContentAreaFilled(false);

        nine.setForeground(Color.BLUE);
        nine.setFont(new Font(Font.SERIF, Font.BOLD, 16));
        nine.setContentAreaFilled(false);


        //为按钮添加监听事件
        H.addActionListener(this);
        C.addActionListener(this);
        DEL.addActionListener(this);
        sum.addActionListener(this);
        minus.addActionListener(this);
        mul.addActionListener(this);
        div.addActionListener(this);
        point.addActionListener(this);
        eql.addActionListener(this);
        zero.addActionListener(this);
        one.addActionListener(this);
        two.addActionListener(this);
        three.addActionListener(this);
        four.addActionListener(this);
        five.addActionListener(this);
        six.addActionListener(this);
        seven.addActionListener(this);
        eight.addActionListener(this);
        nine.addActionListener(this);
        LK.addActionListener(this);
        RK.addActionListener(this);

        //GridBagLayout(网格包布局管理器)
        GridBagLayout gblayout = new GridBagLayout();
        //创建GridBagLayout布局管理器

        p.setLayout(gblayout);
        //使用GridBagLayout布局管理器

        GridBagConstraints g = new GridBagConstraints();

        g.fill = GridBagConstraints.BOTH;//设置当某个单元格未填满时填满整个空间
        //fill
        //指定组件填充网格的方式,可以是如下值:GridBagConstraints.NONE(默认值)、
        // GridBagConstraints.HORIZONTAL(组件横向充满显示区域,但是不改变组件高度)、
        // GridBagConstraints.VERTICAL(组件纵向充满显示区域,但是不改变组件宽度)
        // GridBagConstraints.BOTH(组件横向、纵向充满其显示区域)。

        g.weightx = 1.0;//设置窗口变大时缩放比例
        g.weighty = 1.0;
        //weightx 和 weighty
        //用来指定在容器大小改变时,增加或减少的空间如何在组件间分配,默认值为 0,
        // 即所有的组件将聚拢在容器的中心,多余的空间将放在容器边缘与网格单元之间。
        // weightx 和 weighty 的取值一般在 0.0 与 1.0 之间,数值大表明组件所在的行或者列将获得更多的空间。

        g.gridx = 0;//定位在第一行第一列
        g.gridy = 0;
        //gridx 和 gridy
        //用来指定组件左上角在网格中的行和列。容器中最左边列的 gridx 为 0,最上边行的 gridy 为 0。
        // 这两个变量的默认值是 GridBagConstraints.RELATIVE,表示对应的组件将放在前一个组件的右边或下面。

        g.gridwidth = GridBagConstraints.REMAINDER;//填满整行
        g.gridheight = 1;//占一行网格
        gridwidth 和 gridheight
        //用来指定组件显示区域所占的列数和行数,以网格单元而不是像素为单位,默认值为 1

        g.insets = new Insets(5, 5, 0, 5);
        //设置该组件与其它组件的距离
        // insets指定组件显示区域的外部填充,即组件与其显示区域边缘之间的空间,默认组件没有外部填充。

        gblayout.setConstraints(showexp, g);//设置文本控件位置
        g.gridx = 0;
        g.gridy = 1;//设置在第二行第一列
        g.gridheight = 2;//占两行网格
        g.insets = new Insets(0, 5, 5, 5);

        gblayout.setConstraints(show, g);
        g.gridwidth = 1;
        g.gridheight = 1;//占一行网格且填满整行
        g.insets = new Insets(5, 5, 5, 5);

        g.gridy = 4;//第五行
        g.gridx = 0;
        gblayout.setConstraints(C, g);
        g.gridx = 1;
        gblayout.setConstraints(DEL, g);
        g.gridx = 2;
        gblayout.setConstraints(LK, g);
        g.gridx = 3;
        gblayout.setConstraints(RK, g);

        g.gridy = 5;
        g.gridx = 0;
        gblayout.setConstraints(seven, g);
        g.gridx = 1;
        gblayout.setConstraints(eight, g);
        g.gridx = 2;
        gblayout.setConstraints(nine, g);
        g.gridx = 3;
        gblayout.setConstraints(div, g);

        g.gridy = 6;
        g.gridx = 0;
        gblayout.setConstraints(four, g);
        g.gridx = 1;
        gblayout.setConstraints(five, g);
        g.gridx = 2;
        gblayout.setConstraints(six, g);
        g.gridx = 3;
        gblayout.setConstraints(mul, g);

        g.gridy = 7;
        g.gridx = 0;
        gblayout.setConstraints(one, g);
        g.gridx = 1;
        gblayout.setConstraints(two, g);
        g.gridx = 2;
        gblayout.setConstraints(three, g);
        g.gridx = 3;
        gblayout.setConstraints(sum, g);

        g.gridy = 8;
        g.gridx = 0;
        gblayout.setConstraints(point, g);
        g.gridx = 1;
        gblayout.setConstraints(zero, g);
        g.gridx = 2;
        gblayout.setConstraints(eql, g);
        g.gridx = 3;
        gblayout.setConstraints(minus, g);

        p.add(showexp);
        p.add(show);
        p.add(H);
        p.add(C);
        p.add(DEL);
        p.add(div);
        p.add(seven);
        p.add(eight);
        p.add(nine);
        p.add(mul);
        p.add(four);
        p.add(five);
        p.add(six);
        p.add(minus);
        p.add(one);
        p.add(two);
        p.add(three);
        p.add(sum);
        p.add(zero);
        p.add(point);
        p.add(eql);
        p.add(LK);
        p.add(RK);


        f.setContentPane(p);
        f.setSize(450, 550); //设置窗口尺寸
        f.setLocationRelativeTo(null);
        f.setVisible(true);   //设置窗口是否可见

    }

    //算式合法性
    @Override
    public void actionPerformed(ActionEvent e) {
        output = "";
        if ((e.getSource()) == C) {//清空算式
            input = "0";
            show.setText(input); //显示文本框内容
        } else if ((e.getSource()) == DEL) {
            //提取字符串开始到倒数第二个字符
            input = input.substring(0, input.length() - 1);
            if (input.length() == 0) input = "0";
            show.setText(input);
        } else if ((e.getSource()) == sum || (e.getSource()) == minus || (e.getSource()) == mul || (e.getSource()) == div) {
            if (input.length() != 0 && (!isOperator(input.charAt(input.length() - 1))))//确认必须有数字才能输入运算符
                input += e.getActionCommand(); //getActionCommand():返回于此动作相关的命令字符串
            show.setText(input);
        } else if ((e.getSource()) == point) {
            int pos = input.lastIndexOf('.');//找到最后一个小数点的位置

            if (pos >= 0)//前后两个小数点间不能都是数字,即不能2.33时又添加一个小数点变为2.33.
            {
                if (isDigit(input.charAt(input.length() - 1)) && !isDigitSring(input.substring(pos + 1)))
                    input += e.getActionCommand();
            } else {//小数点前一个必须是数字
                if (isDigit(input.charAt(input.length() - 1)))
                    input += e.getActionCommand();
            }
            show.setText(input);
        } else if ((e.getSource()) == eql) {
            input += '#';//算式末尾添加’#’
            //从算式中拆分出数字
            String[] nums = input.split("[^.0-9]"); //将字符串分割为子字符串,然后结果以字符串数组返回
            //任何字符除了.、0-9
            List<Double> numList = new ArrayList<>();
            for (int i = 0; i < nums.length; i++) {//将每个数字串转化为Double类型
                if (!"".equals(nums[i]))
                    numList.add(Double.parseDouble(nums[i]));
            }
            double out = getValueOfMid(input, numList);//利用中缀式求值
            output = "" + out;//将求得的结果转为字符串


            input = input.substring(0, input.length() - 1);//去除算式后的’#’
            showexp.setText(input);//第一个单行文本框展示算式
            show.setText(output);//第二个单行文本框显示结果
            input = "";//存储算式的字符串清空
        } else {
            if (input == "0") input = "";
            input += e.getActionCommand();
            show.setText(input);
        }

    }

    public static boolean isDigit(char ch)//判断一个字符是否为数字
    {
        return (ch >= '0' && ch <= '9');
    }

    public boolean isDigitSring(String s)//判断一个字符是否都为数字
    {
        for (int i = 0; i < s.length(); i++) {
            if (!isDigit(s.charAt(i)))
                return false;
        }
        return true;
    }

    public boolean isOperator(char c)//判断一个字符是否为运算符或’.’或括号
    {
        return (c == '+') || (c == '-') || (c == '*') || (c == '/') || (c == '.') || (c == '(');
    }

    public static int isp(char ch)//定义栈内运算符优先级,并将相应算符的优先级返回
    {
        switch (ch) {
            case ')':
                return 4;
            case '*':
                return 3;
            case '/':
                return 3;
            case '+':
                return 2;
            case '-':
                return 2;
            case '(':
                return 1;
            case '#':
                return 0;
        }
        return -1;
    }

    public static int icp(char ch)//定义栈外运算符优先级,并将相应算符的优先级返回
    {
        switch (ch) {
            case ')':
                return 1;
            case '*':
                return 3;
            case '/':
                return 3;
            case '+':
                return 2;
            case '-':
                return 2;
            case '(':
                return 4;
            case '#':
                return 0;
        }
        return 0;
    }

    public static double compute(double a, char ch, double b)//将取出的两个操作数与对应的算符进行计算并返回计算结果
    {
        switch (ch) {
            case '+':
                return a + b;
            case '-':
                return a - b;
            case '*':
                return a * b;
            case '/':
                return a / b;
            default:
                break;
        }
        return 0;
    }


    //对输入的算式(中缀式)进行求值
    public static double getValueOfMid(String input, List<Double> numList) {
        Stack<Character> OP = new Stack<>();//定义算符栈
        Stack<Double> OPN = new Stack<>();//定义操作数栈
        double output = 0;//最终结果
        double a, b;//定义两个操作数
        char sym;//定义运算符
        OP.push('#');


        int i = 0, j = 0;
        while (input.charAt(i) != '#' || OP.peek() != '#') //peek():返回栈顶元素但不移除它
        {

            if (isDigit(input.charAt(i)))//数字直接入OPN栈
            {//此字符是数字
                while (isDigit(input.charAt(i)) || input.charAt(i) == '.')//此字符是数字或者此字符是·
                {
                    i++;//跳过此字符
                    if (i == input.length())
                        break;
                }
                i--;
                OPN.push(numList.get(j)); //操作数入栈
                j++;
            } else {//扫描到是操作符

                sym = OP.peek();
                int m = isp(sym); //m为栈内运算符
                int n = icp(input.charAt(i));//n为栈外元素

                if (m < n || n == '(') OP.push(input.charAt(i));// //这个运算符比OP栈顶运算符的优先级高,则入栈;

                else if (m > n || m == n)//这个运算符比OP栈顶运算符优先级低
                {
                    sym = OP.peek();
                    OP.pop();//取出栈内的运算符

                    if (sym != '(' && (m == n || m > n)) {
                        b = OPN.peek();//从操作数栈取出一个操作数
                        OPN.pop();
                        if (!OPN.empty() && OP.peek() != '(')//当操作数栈不为空且不为’(’时继续取出栈中的数进行运算
                        {
                            a = OPN.peek();
                            OPN.pop();
                            OPN.push(compute(a, sym, b));
                            continue;

                        } else//处理负数
                        {
                            switch (sym)//实现一元运算符的运算
                            {
                                case '+':
                                    OPN.push(b);
                                    break;
                                case '-':
                                    OPN.push(-b);
                                    break;
                            }
                            continue;
                        }

                    }
                }
            }
            i++;
        }
        output = OPN.peek();
        return output;
    }
}







package shixi;

//BackgroundPanel类中的代码
import java.awt.Graphics;
import java.awt.Image;
import javax.swing.JPanel;

//继承Jpanel类创建一个可以添加背景的面板类
class BackgroundPanel extends JPanel{
    private Image image = null;

    public BackgroundPanel(Image image) {
        this.image = image;
    }
    // 固定背景图片,允许这个JPanel可以在图片上添加其他组件
    protected void paintComponent(Graphics g) {
        g.drawImage(image, 0, 0, this.getWidth(), this.getHeight(), this);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值