Java实训作业二(简易计算器的设计)

本次实训作业为,设计一个简易的计算器

目录

一、作业要求:

二、主要功能需求分析

三、参考代码


一、作业要求:

1、设计一个简易计算器的GUI窗口,窗口标题上必须含有学生姓名信息。窗口外观、按钮颜色、布局风格随意,但要求简洁、美观。

2、每个班级刻录一张光盘,光盘封面写上班级信息、课程信息、指导老师姓名,如:2018计算机1班《Java实训作业》,指导老师:谢祥选。

3、在光盘上建立一个【班级】目录,在班级目录下再以【学号_姓名】方式创建学生目录,班级和学生目录请使用汉字中括符(【】)括起来,学生目录中的学号与姓名之间的连接符为英文的下划线(_),不是减号(-)。

4、把要上交的作品的项目根目录或项目工作空间目录完整的复制到学生自已的文件夹中,上交的作业中的项目目录不能用中括符(【】)括起来,必须保留开发时的原始目录结构与名称。

上交的作品光盘目录结构如下:

光盘F:\

  |----【18计算机1班】

             |----【20180324_张三丰】

                          |----LoginFrame

                                   |----.idea

                                   |----out

                                   |----src

                          |----MyNotepad

                                   |----.idea

                                   |----out

                                   |----src

             |----20180325_李四光

                          |----MyCalculator

                                   |----.idea

                                   |----out

                                   |----src

                          |----MyNotepad

                                   |----.idea

                                   |----out

                                   |----src

             |----20180368_小宇飞刀

                          |----LoginFrame

                                   |----.idea

                                   |----out

                                   |----src

                          |----MyNotepad

                                   |----.idea

                                   |----out

                                   |----src

       ……

二、主要功能需求分析

1、设计一个简易计算器的GUI窗口,窗口标题上必须含有学生姓名信息。窗口外观、按钮颜色、布局风格随意,但要求简洁、美观可。

2、至少包含下图所示的计算功能(加减乘除,正负数、次幂、求余),如图:

3、完成一个计算器其他应有的功能。

三、参考代码

对一个网上比较小巧的计算器程序进行了修改,原作者的类设计规划合理,代码风格优良,注释详尽,非常值得借鉴。感谢原作者:https://blog.csdn.net/weixin_36279318/article/details/78486900

我在作者的设计上扩展几个本次实训作业需要完成的功能:

  • 1、←(退格键)
  • 2、± (正负数)
  • 3、^ (求次幂)
  • 4、%(求余数)

实例截图:

  

扩展版的参考代码:

/**
 * 文件名:Calculator.java
 * 功能描述:简易计算器
 */
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;

@SuppressWarnings("serial")
class CalculatorPanel extends JPanel {
    private Font font = new Font(Font.MONOSPACED,Font.BOLD,14);
    private JPanel jp; // 中间的面板
    private double result; // 计算结果
    private boolean start; // 用于判断是否是首次输入,true首次,false不是首次
    private boolean flag; // 用于判断是否清空显示区域的值,true需要,false不需要
    private String lastCommand; // 用于保存运算符
    JTextField display; // 显示区域

    public CalculatorPanel() {
        // 初始化各项值
        result = 0;
        start = true;
        flag = false;
        lastCommand = "=";

        // 设置CalculatorPanel这个面板的布局为框架布局
        setLayout(new BorderLayout());
        // 这个按钮用来显示值的区域
        display = new JTextField("0.0",30);
        display.setFont(font);
        //将文本内容设置在文本框的左边
        display.setHorizontalAlignment(display.RIGHT);
        display.setEnabled(false);// 按钮样式设置为禁用样式

        // 用来初始化,清除用的
        JButton clear = new JButton("清除");
        clear.setFont(font);
        clear.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // 作初始化的操作
                result = 0;
                start = true;
                flag = false;
                lastCommand = "=";
                display.setText("0.0");
            }
        });

        jp = new JPanel();
        // 将此面板布局设置为网格布局,4行4列
        jp.setLayout(new GridLayout(5, 4));

        // 实例化监听器对象
        NumberAction numAction = new NumberAction();
        CommandAction cmdAction = new CommandAction();

        makeButton("7", numAction);
        makeButton("8", numAction);
        makeButton("9", numAction);
        makeButton("←", numAction);

        makeButton("4", numAction);
        makeButton("5", numAction);
        makeButton("6", numAction);
        makeButton("/", cmdAction);

        makeButton("1", numAction);
        makeButton("2", numAction);
        makeButton("3", numAction);
        makeButton("*", cmdAction);

        makeButton("0", numAction);
        makeButton(".", numAction);
        makeButton("=", cmdAction);
        makeButton("-", cmdAction);

        makeButton("±", cmdAction);
        makeButton("^", cmdAction);
        makeButton("%", cmdAction);
        makeButton("+", cmdAction);

        // 将面板,两个按键加入到我的面板,实现计算器的界面
        add(display, BorderLayout.NORTH);
        add(jp, BorderLayout.CENTER);
        add(clear, BorderLayout.SOUTH);

    }

    private void makeButton(String buttonName, ActionListener al) {
        JButton jb = new JButton(buttonName);
        jb.setFont(font);
        jp.add(jb);
        jb.addActionListener(al);
    }

    // 数字监听器
    private class NumberAction implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            JButton jb = (JButton) e.getSource(); // 获取事件源对象
            String input = jb.getText(); // 获取事件源对象上的标签
            if (start) { // 首次输入
                // 一上就".",就什么也不做
                if (input.equals(".")) {
                    return;
                }
                if (input.equals("←")) {
                    return;
                }
                // 如果是"0.0"的话,就清空
                if (display.getText().equals("0.0")) {
                    display.setText("");
                }
                start = false;// 改变是否首次输入的标记值
            } else {
                if (input.equals("←")) {
                    String s = display.getText();
                    if (Math.abs(Double.valueOf(display.getText()))>0.0) {
                        s = s.substring(0,s.length()-1);
                        if (s.equals("")) {
                            s = "0.0";
                            start = true;
                        }
                        display.setText(s);
                    }
                    return;
                }
                // 判断显示区域的值里面是否已经有".",如果有,输入的又是".",就什么都不做
                if (display.getText().indexOf(".") != -1) {
                    if (input.equals(".")) {
                        return;
                    }
                }

                // 判断显示区域的值里面只有"-",输入的又是".",就什么都不做
                if (display.getText().equals("-")) {
                    if (input.equals(".")) {
                        return;
                    }
                }

                // 判断显示区域的值如果是"0",输入的不是".",就什么也不做
                if (display.getText().equals("0")) {
                    if (!input.equals(".")) {
                        return;
                    }
                }
            }
            // 如果我点击了运算符以后,再输入数字的话,就要清空显示区域的值
            if (flag) {
                display.setText("");
                flag = false;// 还原初始值,不需要清空
            }
            display.setText(display.getText() + input);// 设置显示区域的值
        }
    }

    // 运算符监听器
    private class CommandAction implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            JButton jb = (JButton) e.getSource(); // 获取事件源对象
            String inputCommand = jb.getText(); // 获取事件源对象上的标签

            if (start) {// 首次输入
                // 一上就是"-"
                if (inputCommand.equals("-") || inputCommand.equals("±")) {
                    display.setText("-");// 显示区域的内容设置为"-"
                    start = false;// 改变首次输入的标记
                }
            } else {
                if (inputCommand.equals("±")) {
                    double x = Double.parseDouble(display.getText());
                    x = -x;
                    display.setText(String.valueOf(x));
                    return;
                }

                if (!flag) {// 如果flag=false不需要清空显示区的值,就调用方法计算
                    calculate(Double.parseDouble(display.getText()));// 保存显示区域的值,并计算
                }
                // 保存你点击的运算符
                lastCommand = inputCommand;
                flag = true;// 因为我这里已经输入过运算符,
            }
        }
    }

    // 计算用的方法
    private void calculate(double x) {
        if (lastCommand.equals("+")) {
            result += x;
        } else if (lastCommand.equals("-")) {
            result -= x;
        } else if (lastCommand.equals("*")) {
            result *= x;
        } else if (lastCommand.equals("/")) {
            result /= x;
        } else if (lastCommand.equals("%")) {
            result %= x;
        } else if (lastCommand.equals("^")) {
            result = Math.pow(result,x);
        } else if (lastCommand.equals("±")) {
            result = -result;
        } else if (lastCommand.equals("=")) {
            result = x;
        }
        display.setText("" + result);
    }
}

class MyFrameUitl {
    public static void init(JFrame jFrame, Dimension frameSize, String title,
                            String iconFileName, boolean resizable) {
        // 系统工具包,可以读取系统信息
        Toolkit tk = Toolkit.getDefaultToolkit();
        // 获取屏幕大小
        Dimension screenSize = tk.getScreenSize();
        // 获取宽高
        int screenWidth = screenSize.width;
        int screenHeight = screenSize.height;

        // 找中心点
        int centerX = screenWidth / 2;
        int centerY = screenHeight / 2;

        // 解析窗体大小
        int frameWidth = frameSize.width;
        int frameHeight = frameSize.height;

        // 设置窗体位置
        jFrame.setBounds(centerX - frameWidth / 2, centerY - frameHeight / 2,
                frameWidth, frameHeight);
        jFrame.setTitle(title);// 设置标题
        if (iconFileName != null) {
            jFrame.setIconImage(tk.getImage(iconFileName));// 设置图标
        }

        // 设置皮肤com.sun.java.swing.plaf.windows.WindowsLookAndFeel
        /**/
        try {
            UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
            SwingUtilities.updateComponentTreeUI(jFrame);
        } catch (Exception e1) {
            e1.printStackTrace();
        }

        jFrame.setLocationRelativeTo(null);
        jFrame.setResizable(resizable);// 设置窗体是否可以改变大小
        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 设置程序关闭动作
        jFrame.setVisible(true);// 显示窗体

    }
}

class CalculatorFrame extends JFrame {
    public CalculatorFrame() {
        add(new CalculatorPanel());
        MyFrameUitl.init(this, new Dimension(800, 600), "简易计算器(xieyunc)", null,
                false);
        // 让组件按原始大小显示,并且窗体的大小刚好能够容纳所有的组件
        this.pack();
    }
}

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