第二次作业

[实验目的]

1.掌握软件开发的基本流程

2.掌握常用的软件开发方式和工具。

[实验内容]

1.设计一个包含登录界面的计算器软件,该软件可以实现第一次作业中的全部功能,同时可以保存用户的历史计算记录(保存数据最好使用数据库)。

一、使用软件及环境

1.boardmix与viso professional绘制流程图

2.idea编写Java代码

3.MySql编写数据库

二、流程图绘制

1.登陆界面流程图

 2.计算器流程图

 

 三、实现实验内容

1.登陆器部分

第一步先要实现登陆器的UI设计,创建一个新窗口添加账户输入和密码输入,添加登录和注册按钮实现用户的登录注册,以下是用户登陆器界面UI设计代码

用户登录节目UI

复制代码
package calculator;

import java.awt.*;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;
import javax.swing.text.JTextComponent;

public class UserUI {
    public void initUI(){
        System.out.println ("UserUI");
        //界面
        JFrame jF = new JFrame ("用户界面");
        jF.setSize (600, 600);          //窗体大小
        jF.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);//窗体关闭方式
        jF.setLocationRelativeTo (null);// 居中
        jF.setLayout (new FlowLayout ());
        JLabel text = new JLabel("请登录或者注册",SwingConstants.CENTER);
        text.setFont(new Font("宋体",Font.PLAIN,30));
        text.setPreferredSize(new Dimension(600,30));
        //创建组件对象
        JLabel accountjla = new JLabel ("账号: ",SwingConstants.CENTER);
        accountjla.setFont(new Font("宋体",Font.PLAIN,20));
        accountjla.setPreferredSize(new Dimension(200,30));
        JTextField account = new JTextField (60);// 60个字符宽度
        JLabel passwordjla = new JLabel ("密码: ",SwingConstants.CENTER);
        passwordjla.setFont(new Font("宋体",Font.PLAIN,20));
        passwordjla.setPreferredSize(new Dimension(200,30));
        JPasswordField password = new JPasswordField (60);// 60个字符宽度
        JButton login = new JButton ("登录");
        JButton regist = new JButton ("注册");
        // 添加组件 按顺序添加
        jF.add(text);
        jF.add (accountjla);
        jF.add (account);
        jF.add (passwordjla);
        jF.add (password);
        jF.add (login);
        jF.add (regist);
        jF.setVisible (true);
        // 创建监听器对象 并添加给登录注册按钮
        UIListener uiListener = new UIListener ();
        login.addActionListener (uiListener);
        regist.addActionListener (uiListener);
        // 将界面上的输入框对象变量名 中存储的输入框对象地址 复制一份给监听器对象中输入框对象变量名
        uiListener.accountjtf = account;
        uiListener.passwordjpf = password;
    }
    public static void main(String[] args){
        new UserUI ().initUI ();
    }
}
复制代码

在登录界面的最后创建用户登录监听器,将用户输入的用户ID和用户密码password传给用户登录监听器,以便监听器使用并判断用户输入的信息合法性

2.用户登陆监听器部分

监听器的作用主要为判断用户登录与注册的合法性,并将合法记录传给数据库记录在用户表中,合法ID传给计算器使用,并提示非法输入的信息给用户以便用户进行修改与订正

以下为用户登陆监听器代码

用户登录监听器

复制代码
package calculator;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.sql.ResultSet;

public class UIListener implements ActionListener {
    JTextField accountjtf;
    JPasswordField passwordjpf;
    // 创建一个用户数组
    User[] userList = new User[10];
    int index = 0;
    connectionMySql con = new connectionMySql();
    // 重写点击按钮会调用的方法
// ActionEvent 动作事件 用来获取当前被点击的按钮的信息
    @Override
    public void actionPerformed(ActionEvent e) {
// 获取 按钮上的文本 用来判断是哪个按钮被点击了
        String ac = e.getActionCommand();
// 获取输入框中的账号密码 进行验证 登录 注册
        String account = accountjtf.getText();
        String password = passwordjpf.getText();
        System.out.println("账号: " + account + " 密码: " + password);
        if (account.equals("") || password.equals("")) {
            JOptionPane.showMessageDialog(null, "账号或密码不能为空");
            return;
        }
        con.openMySql();
        if (ac.equals("登录")) {
            System.out.println("登录按钮被点击了");
// 验证这个账号是否已经被注册过
            try {
                String selectSql = "select userpass from users where userid = '" + account + "'";
                ResultSet res = con.select(selectSql);
                String userPass = "";
                while (res.next()) {
                    userPass = res.getString("userpass");
                }
                if (userPass.equals("") || userPass.equals(null)) {
                    //用户不存在
                    JOptionPane.showMessageDialog(null, "账号不存在,请先注册~");
                } else if (userPass.equals(password)) {
                    //登录成功
                    JOptionPane.showMessageDialog(null, "登录成功");
                    calculator cal = new calculator(account);
                } else {
                    //用户名或密码错误
                    JOptionPane.showMessageDialog(null, "登录错误");
                }
            } catch (Exception e1) {
                e1.printStackTrace();
            }
        } else if (ac.equals("注册")) {
            System.out.println("注册按钮被点击了");
// 验证这个账号是否已经被注册过
            try {
                String selectSql = "select userid from users where userid = '" + account + "'";
                ResultSet resu = con.select(selectSql);
                String userId = "";
                while (resu.next()) {
                    userId = resu.getString("userid");
                }
                if (userId.equals(account)) {
                    //用户存在
                    JOptionPane.showMessageDialog(null, "账号已经被注册过了");
                } else if (userId.equals("") || userId.equals(null)) {
                    //用户不存在
                    JOptionPane.showMessageDialog(null, "注册成功,请登录~");
                    String sql = "INSERT INTO users VALUE('" + account + "','" + password + "')";
                    con.update(sql);
                }
            } catch (Exception e1) {
                e1.printStackTrace();
            }
        }
    }
}
复制代码

当用户输入ID和密码,并点击登录键,会进入判断,此时调用数据库中与用户输入ID相对应的用户密码,若用户密码为空,则说明这个ID并未创建,则反馈用户提示:账户不存在,请先注册,若用户密码非空且与用户输入密码相同,则反馈用户提示:登录成功,打开计算器并传ID给计算器,若用户密码非空且与用户输入密码不同,则反馈用户提示:登录错误

当用户输入ID和密码,并点击注册键,会进入判断,此时调用数据库中与用户输入ID相对应的用户ID,若用户ID不为空且与用户输入ID相同,则说明用户账户已被注册,反馈用户提示:账户已经被注册过了,若用户ID为空,说明用户账户未被注册,则反馈用户提示:注册成功,请登录,并传用户输入的ID和密码给数据库users表保存

3.计算器部分

计算器部分在用户登录成功后会被打开,并接收监听器传来的用户ID,此时用户可在打开的计算器上计算计算结果会和监听器传递的用户ID一起传回数据库中的usercalcu表储存用户计算公式和用户计算结果,计算器部分分别为界面和传输部分,计算实现部分,前者为calculator,后者为calculate,以下为计算器部分代码

计算器calculator

复制代码
package calculator;

// 导入自己的计算类

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.math.BigDecimal;


// 计算器界面
public class calculator extends JFrame implements ActionListener {
    connectionMySql con= new connectionMySql();

    // 获得显示屏大小
    public static final int SCREAM_HEIGHT = (int) Toolkit.getDefaultToolkit().getScreenSize().getHeight();
    public static final int SCREAM_WIDTH = (int) Toolkit.getDefaultToolkit().getScreenSize().getWidth();
    // 根据显示屏高度设定计算器界面大小
    private static final int EXAMPLE = (int) (SCREAM_HEIGHT / 4.32);


    // 字体大小
    Font cu = new Font("粗体", Font.BOLD, (int) (EXAMPLE * 0.2));


    /**********************************************超级初始化块*******************************************************/


    protected void __init__() {
        // 设置窗口名称
        this.setTitle("计算器");
        // 4比3固定窗口
        this.setSize(EXAMPLE * 3, EXAMPLE * 4);
        this.setResizable(false);
        this.setLocationRelativeTo(null);
        // 设置窗口可见
        this.setVisible(true);
        this.setBackground(Color.black);
        // 设置关闭按钮(释放进程)
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
        // 设置方向布局
        this.setLayout(new BorderLayout());
    }


    /**********************************************北国风光*******************************************************/

    // 北面组件
    private JPanel northBox = new JPanel(new FlowLayout());
    private JTextField input = new JTextField();
    private JButton clear = new JButton();


    // 设置北面组件
    private void setNorth() {
        // 设置数字栏
        this.input.setPreferredSize(new Dimension((int) (EXAMPLE * 2.2), (int) (EXAMPLE * 0.4)));
        this.input.setFont(this.cu);
        this.input.setForeground(Color.BLACK);      // 额好像没用,但限制用户输入更重要
        this.input.setEnabled(false);
        this.input.setHorizontalAlignment(SwingConstants.RIGHT);

        // 设置清空
        this.clear.setText("C");
        this.clear.setPreferredSize(new Dimension((int) (EXAMPLE * 0.4), (int) (EXAMPLE * 0.4)));
        this.clear.setFont(this.cu);
        this.clear.setForeground(Color.RED);

        // 安装北仪表
        this.northBox.add(this.input);
        this.northBox.add(this.clear);

        // 安装北仪表到主体
        this.add(this.northBox, BorderLayout.NORTH);
    }


    /**********************************************中央处理器*******************************************************/


    // 中部组件
    private JPanel CPU = new JPanel();
    private JButton[] cal = new JButton[20];
    // 后16个按钮顺序,懒得写集合类了
    String str = "789/456x123-0.=+";

    // 设置中部组件
    private void setCenter() {
        // 划分20格
        this.CPU.setLayout(new GridLayout(5, 4));
        // 设置开方按钮
        this.cal[0] = new JButton();
        this.cal[0].setText("^-2");
        this.cal[0].setPreferredSize(new Dimension((int) (EXAMPLE * 0.2), (int) (EXAMPLE * 0.15)));
        this.cal[0].setFont(this.cu);
        this.cal[0].setForeground(Color.BLUE);
        // 设置括号按钮
        this.cal[1] = new JButton();
        this.cal[1].setText("^2");
        this.cal[1].setPreferredSize(new Dimension((int) (EXAMPLE * 0.2), (int) (EXAMPLE * 0.15)));
        this.cal[1].setFont(this.cu);
        this.cal[1].setForeground(Color.BLUE);
        this.cal[2] = new JButton();
        this.cal[2].setText("(");
        this.cal[2].setPreferredSize(new Dimension((int) (EXAMPLE * 0.2), (int) (EXAMPLE * 0.15)));
        this.cal[2].setFont(this.cu);
        this.cal[2].setForeground(Color.BLUE);

        // 设置清除按钮
        this.cal[3] = new JButton();
        this.cal[3].setText(")");
        this.cal[3].setPreferredSize(new Dimension((int) (EXAMPLE * 0.2), (int) (EXAMPLE * 0.15)));
        this.cal[3].setFont(this.cu);
        this.cal[3].setForeground(Color.BLUE);

        // 设置后16个按钮
        for (int i = 4; i < 20; i++) {
            String temp = this.str.substring(i - 4, i - 3);
            this.cal[i] = new JButton();
            this.cal[i].setText(temp);
            this.cal[i].setPreferredSize(new Dimension((int) (EXAMPLE * 0.2), (int) (EXAMPLE * 0.15)));
            this.cal[i].setFont(this.cu);
            if ("+-x/=".contains(temp)) {
                this.cal[i].setForeground(Color.GRAY);
            }
        }
        // 添加按钮
        for (int i = 0; i < 20; i++) {
            this.CPU.add(this.cal[i]);
        }
        this.add(this.CPU,BorderLayout.CENTER);
    }


    /********************************************** 南柯一梦 *******************************************************/

    public String user;

    public void setUser(String user) {
        this.user = user;
    }

    // 南面组件
    private JLabel message = new JLabel("welcome," + user, SwingConstants.CENTER);

    // 设置南面组件
    private void setSouth() {
        this.message.setText(user);
        this.message.setPreferredSize(new Dimension((int) (EXAMPLE * 0.1), (int) (EXAMPLE * 0.1)));
        this.message.setForeground(Color.BLACK);
        this.add(this.message, BorderLayout.SOUTH);
    }


    /*********************************************监听*********************************************************/

    // 给按钮添加监听
    private void setListener() {
        for (JButton j : cal) {
            j.addActionListener(this);
        }
        this.clear.addActionListener(this);
    }

    // 监听事件设置
    @Override
    public void actionPerformed(ActionEvent e) {
        String listen = e.getActionCommand();
        if ("0.1^23456789+-x/()^-2".contains(listen)) {
            this.input.setText(this.input.getText() + listen);
        }
        this.bigWork(listen);
    }


    /*****************************************状态**************************************************/

    // 小数点信号
    private Boolean pointSignal = false;
    // 括号信号
    private int barcketNum = 0;

    private String num = "0123456789";
    private String sign = "+-x/(";

    // 输入的最后一位为数字时的状态,详细见详细设计表格
    public void inNum() {
        // 只能输入pow函数,右括号,数字和符号按钮,不能输入左括号,若小数点信号为真,则可以输入小数点
        for (int i=0;i<20;i++) {
            if("(".equals(this.cal[i].getText())) {
                this.cal[i].setEnabled(false);
            }
            else {
                this.cal[i].setEnabled(true);
            }
        }
        // 根据信号设置
        this.cal[17].setEnabled(this.pointSignal);
    }

    // 输入的最后一位为符号或左括号时
    public void inSign() {
        // 只能输入非小数点数字及左括号,小数点信号开启
        for (int i=0;i<20;i++) {
            if("(".equals(this.cal[i].getText()) || this.num.contains(this.cal[i].getText())) {
                this.cal[i].setEnabled(true);
            }
            else {
                this.cal[i].setEnabled(false);
            }
        }
        this.pointSignal = true;
    }

    // 输入最后一位为右括号或pow运算时
    public void inPow() {
        // 只能输入符号和右括号和pow函数
        for (int i=0;i<20;i++) {
            if("(".equals(this.cal[i].getText()) || this.num.contains(this.cal[i].getText()) || ".".equals(this.cal[i].getText())) {
                this.cal[i].setEnabled(false);
            }
            else {
                this.cal[i].setEnabled(true);
            }
        }
    }

    // 输入最后一位为小数点时
    public void inPoint() {
        // 只能输入非小数点数字,小数点信号关闭
        for (int i=0;i<20;i++) {
            if(this.num.contains(this.cal[i].getText())) {
                this.cal[i].setEnabled(true);
            }
            else {
                this.cal[i].setEnabled(false);
            }
        }
        this.pointSignal = false;
    }

    public void inEqual() {
        for (int i=0;i<20;i++) {
            this.cal[i].setEnabled(false);
        }
    }


    /*****************************************核酸隔离点*********************************************/


    // 真正的超级初始化块
    public calculator() throws HeadlessException {
        // 界面设置
        this.__init__();
        this.setNorth();
        this.setCenter();
        this.setSouth();
        // 交互设置
        this.setListener();
        JOptionPane.showMessageDialog(this, "由于框架原因,本计算器打开时可能按钮显示不全,请最小化后打开");
        this.inSign();
        this.calculate.refresh();
    }


    calculate calculate = new calculate();
    private String temStr = "";

    // 记录公式及答案为后续拓展提供api
    private String caled;
    private String ans;

    public void setCaled(String caled) {
        this.caled = caled;
    }

    public void setAns(BigDecimal ans) {
        this.ans = ans.toString();
    }

    public String getCaled() {
        return caled;
    }

    public String getAns() {
        return ans;
    }

    // 控制器
    public void bigWork(String listen) {
        
        // 记录括号信号
        if ("(".equals(listen)) {
            this.barcketNum++;
        }
        if (")".equals(listen)) {
            this.barcketNum--;
        }
        
        // 基础状体转换
        if (this.num.contains(listen)) {
            this.temStr = this.temStr +listen;
            this.inNum();
        } else if (this.sign.contains(listen)) {
            if(!"".equals(temStr)) {
                this.calculate.numPush(this.temStr);
                this.temStr = "";
            }
            this.calculate.calIOC(listen);
            this.inSign();
        } else if (")".equals(listen) || listen.contains("^")) {
            if(!"".equals(temStr)) {
                this.calculate.numPush(this.temStr);
                this.temStr = "";
            }
            if (listen.contains("^")) {
                calculate.powIOC(listen);
            } else {
                this.calculate.barcketIOC();
            }
            this.inPow();
        } else if (".".equals(listen)) {
            this.temStr = this.temStr +listen;
            this.inPoint();
        }  else if ("=".equals(listen)) {
            if(!"".equals(temStr)) {
                this.calculate.numPush(this.temStr);
                this.temStr = "";
            }
            this.setCaled(this.input.getText());
            this.setAns(this.calculate.equaIOC());
            con.openMySql();
            String insertSql = "INSERT INTO usercalcu VALUES ('" + user + "','" + caled + "'," + ans + ")";
            con.update(insertSql);
            this.input.setText(this.ans);
            this.inEqual();
        }else if ("C".equals(listen)) {
            this.calculate.refresh();
            this.input.setText("");
            this.temStr = "";
            this.barcketNum = 0;
            this.inSign();
        } else {
            JOptionPane.showMessageDialog(this, "error : unvaild input");
        }
        
        // 限制用户输入
        if (this.barcketNum < 0) {
            JOptionPane.showMessageDialog(this,"error : wrong number of barcket");
        }
        if(this.barcketNum == 0) {
            this.cal[3].setEnabled(false);
        }

        if (this.barcketNum > 0) {
            this.cal[18].setEnabled(false);
        }
    }

    public calculator(String uname) throws HeadlessException{
        // 界面设置
        this.__init__();
        this.setNorth();
        this.setCenter();
        // 获取uname
        this.setUser(uname);
        this.setSouth();
        // 交互设置
        this.setListener();
        JOptionPane.showMessageDialog(this, "由于框架原因,本计算器打开时可能按钮显示不全,请最小化后打开");
        this.inSign();
        this.calculate.refresh();
    }



    // 软件测试


}
复制代码

计算器calculate

复制代码
package calculator;


import java.math.BigDecimal;
import java.util.Stack;


public class calculate {

    // 符号栈
    private Stack<String> signStack = new Stack();

    // 数字栈
    private Stack<BigDecimal> numStack = new Stack();


    /*******************************************将军的恩情还不完*************************************************/


    // 额switch可以判断引用类型变量的值相等吗{0:'+', 1:'-', 2:'x', 3:'/'}
    private static final String signCode = "+-x/()";

    // 计算器主体模块
    public BigDecimal work(BigDecimal caled, BigDecimal cal, String sign) {
        BigDecimal ans = null;
        switch (signCode.indexOf(sign)) {
            case 0:
                ans = caled.add(cal);
                break;
            case 1:
                ans = caled.subtract(cal);
                break;
            case 2:
                ans = caled.multiply(cal);
                break;
            case 3:
                try {
                    ans = caled.divide(cal);
                }catch (ArithmeticException AE) {
                    if(AE.getLocalizedMessage().equals("Non-terminating decimal expansion; no exact representable decimal result."))
                        ans = caled.divide(cal, 5, BigDecimal.ROUND_HALF_UP);
                    else
                        ans = BigDecimal.valueOf(32202);
                    System.out.println("Exception : "+AE.getLocalizedMessage());
                }
                break;
            case 4:
            case 5:
                this.numStack.push(caled);
                ans = cal;
                break;
            default:
                ans = null;
        }
        return ans;
    }

    // 设计开方(牛顿莱布尼兹)
    public static BigDecimal niuton(BigDecimal caled) {
        BigDecimal ans;
        if (caled.doubleValue() < 0) {
            System.out.println("Exception : Negative caled");
            return BigDecimal.valueOf(32202);
        }
        double x = 1;
        double y = x - (x * x - caled.doubleValue()) / (2 * x);
        while (x - y > 0.00000001 || x - y < -0.00000001) {
            x = y;
            y = x - (x * x - caled.doubleValue()) / (2 * x);
        }
        ans = BigDecimal.valueOf(y);
        return ans;
    }

    // 设计平方
    public static BigDecimal square(BigDecimal caled) {
        return caled.pow(2);
    }

    // 设计清屏
    public void refresh() {
        this.numStack.clear();
        this.signStack.clear();
        this.signStack.push("=");
        // 解决计算当(x+y)后输入符号时,需要出栈两个数进行括号运算(即将数按顺序压回去)时数字栈只有一个栈的问题。
        this.numStack.push(new BigDecimal(0));
    }


    /**********************************************入集中营**************************************************/

    // 索引,见详细设计
    private String index = "+-x/()=";

    // 数据,见详细设计^^_  ,>为0,<为1,=为2,null为3
    private int[][] compareToSign = {{0, 0, 1, 1, 1, 0, 0}, {0, 0, 1, 1, 1, 0, 0}, {0, 0, 0, 0, 1, 0, 0},
            {0, 0, 0, 0, 1, 0, 0}, {1, 1, 1, 1, 1, 2, 3}, {0, 0, 0, 0, 3, 0, 0}, {1, 1, 1, 1, 1, 3, 2}};


    // 数字入栈
    public void numPush(String decimal) {
        this.numStack.push(new BigDecimal(decimal));
    }

    public void numPush(BigDecimal decimal) {
        this.numStack.push(decimal);
    }


    // 控制流,详细见详细设计p1
    public void calIOC(String topSign) {
        BigDecimal caled, cal;
        String temp;
        temp = this.signStack.peek();
        switch (this.compareToSign[index.indexOf(temp)][index.indexOf(topSign)]) {
            case 0:
                cal = this.numStack.pop();
                caled = this.numStack.pop();
                temp = this.signStack.pop();
                this.numStack.push(this.work(caled, cal, temp));
                this.signStack.push(topSign);
                break;
            case 1:
                this.signStack.push(topSign);
                break;
            case 2:
                this.signStack.pop();
                break;
            default:
                System.out.println("Exception : wrong I/O");
                break;
        }
    }


    // 等号入栈
    public BigDecimal equaIOC() {
        BigDecimal ans, caled, cal;
        String topSign;
        while (!"=".equals(this.signStack.peek())) {
            topSign = this.signStack.pop();
            cal = this.numStack.pop();
            caled = this.numStack.pop();
            this.numStack.push(this.work(caled, cal, topSign));
        }
        ans = this.numStack.pop();
        return ans;
    }

    // pow的IO流控制
    public void powIOC(String topSign) {
        BigDecimal temp;
        temp = this.numStack.pop();
        if (topSign.equals("^2")) {
            this.numStack.push(calculate.square(temp));
        } else {
            this.numStack.push(calculate.niuton(temp));
        }
    }

    public static void main(String[] args) {
        calculate c = new calculate();
        c.numPush("2");
        c.powIOC("^2");
        System.out.println(c.numStack.peek());
    }

    // 通过循环执行运算功能直到左括号为栈顶符号来规避括号内有运算符
    public void barcketIOC() {
        BigDecimal caled, cal;
        String topSign;
        while (!"(".equals(this.signStack.peek())) {
            topSign = this.signStack.pop();
            cal = this.numStack.pop();
            caled = this.numStack.pop();
            this.numStack.push(this.work(caled, cal, topSign));
        }
        this.signStack.pop();
    }


}
复制代码

计算器calculator

复制代码
package calculator;

// 导入自己的计算类

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.math.BigDecimal;


// 计算器界面
public class calculator extends JFrame implements ActionListener {
    connectionMySql con= new connectionMySql();

    // 获得显示屏大小
    public static final int SCREAM_HEIGHT = (int) Toolkit.getDefaultToolkit().getScreenSize().getHeight();
    public static final int SCREAM_WIDTH = (int) Toolkit.getDefaultToolkit().getScreenSize().getWidth();
    // 根据显示屏高度设定计算器界面大小
    private static final int EXAMPLE = (int) (SCREAM_HEIGHT / 4.32);


    // 字体大小
    Font cu = new Font("粗体", Font.BOLD, (int) (EXAMPLE * 0.2));


    /**********************************************超级初始化块*******************************************************/


    protected void __init__() {
        // 设置窗口名称
        this.setTitle("计算器");
        // 4比3固定窗口
        this.setSize(EXAMPLE * 3, EXAMPLE * 4);
        this.setResizable(false);
        this.setLocationRelativeTo(null);
        // 设置窗口可见
        this.setVisible(true);
        this.setBackground(Color.black);
        // 设置关闭按钮(释放进程)
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
        // 设置方向布局
        this.setLayout(new BorderLayout());
    }


    /**********************************************北国风光*******************************************************/

    // 北面组件
    private JPanel northBox = new JPanel(new FlowLayout());
    private JTextField input = new JTextField();
    private JButton clear = new JButton();


    // 设置北面组件
    private void setNorth() {
        // 设置数字栏
        this.input.setPreferredSize(new Dimension((int) (EXAMPLE * 2.2), (int) (EXAMPLE * 0.4)));
        this.input.setFont(this.cu);
        this.input.setForeground(Color.BLACK);      // 额好像没用,但限制用户输入更重要
        this.input.setEnabled(false);
        this.input.setHorizontalAlignment(SwingConstants.RIGHT);

        // 设置清空
        this.clear.setText("C");
        this.clear.setPreferredSize(new Dimension((int) (EXAMPLE * 0.4), (int) (EXAMPLE * 0.4)));
        this.clear.setFont(this.cu);
        this.clear.setForeground(Color.RED);

        // 安装北仪表
        this.northBox.add(this.input);
        this.northBox.add(this.clear);

        // 安装北仪表到主体
        this.add(this.northBox, BorderLayout.NORTH);
    }


    /**********************************************中央处理器*******************************************************/


    // 中部组件
    private JPanel CPU = new JPanel();
    private JButton[] cal = new JButton[20];
    // 后16个按钮顺序,懒得写集合类了
    String str = "789/456x123-0.=+";

    // 设置中部组件
    private void setCenter() {
        // 划分20格
        this.CPU.setLayout(new GridLayout(5, 4));
        // 设置开方按钮
        this.cal[0] = new JButton();
        this.cal[0].setText("^-2");
        this.cal[0].setPreferredSize(new Dimension((int) (EXAMPLE * 0.2), (int) (EXAMPLE * 0.15)));
        this.cal[0].setFont(this.cu);
        this.cal[0].setForeground(Color.BLUE);
        // 设置括号按钮
        this.cal[1] = new JButton();
        this.cal[1].setText("^2");
        this.cal[1].setPreferredSize(new Dimension((int) (EXAMPLE * 0.2), (int) (EXAMPLE * 0.15)));
        this.cal[1].setFont(this.cu);
        this.cal[1].setForeground(Color.BLUE);
        this.cal[2] = new JButton();
        this.cal[2].setText("(");
        this.cal[2].setPreferredSize(new Dimension((int) (EXAMPLE * 0.2), (int) (EXAMPLE * 0.15)));
        this.cal[2].setFont(this.cu);
        this.cal[2].setForeground(Color.BLUE);

        // 设置清除按钮
        this.cal[3] = new JButton();
        this.cal[3].setText(")");
        this.cal[3].setPreferredSize(new Dimension((int) (EXAMPLE * 0.2), (int) (EXAMPLE * 0.15)));
        this.cal[3].setFont(this.cu);
        this.cal[3].setForeground(Color.BLUE);

        // 设置后16个按钮
        for (int i = 4; i < 20; i++) {
            String temp = this.str.substring(i - 4, i - 3);
            this.cal[i] = new JButton();
            this.cal[i].setText(temp);
            this.cal[i].setPreferredSize(new Dimension((int) (EXAMPLE * 0.2), (int) (EXAMPLE * 0.15)));
            this.cal[i].setFont(this.cu);
            if ("+-x/=".contains(temp)) {
                this.cal[i].setForeground(Color.GRAY);
            }
        }
        // 添加按钮
        for (int i = 0; i < 20; i++) {
            this.CPU.add(this.cal[i]);
        }
        this.add(this.CPU,BorderLayout.CENTER);
    }


    /********************************************** 南柯一梦 *******************************************************/

    public String user;

    public void setUser(String user) {
        this.user = user;
    }

    // 南面组件
    private JLabel message = new JLabel("welcome," + user, SwingConstants.CENTER);

    // 设置南面组件
    private void setSouth() {
        this.message.setText(user);
        this.message.setPreferredSize(new Dimension((int) (EXAMPLE * 0.1), (int) (EXAMPLE * 0.1)));
        this.message.setForeground(Color.BLACK);
        this.add(this.message, BorderLayout.SOUTH);
    }


    /*********************************************监听*********************************************************/

    // 给按钮添加监听
    private void setListener() {
        for (JButton j : cal) {
            j.addActionListener(this);
        }
        this.clear.addActionListener(this);
    }

    // 监听事件设置
    @Override
    public void actionPerformed(ActionEvent e) {
        String listen = e.getActionCommand();
        if ("0.1^23456789+-x/()^-2".contains(listen)) {
            this.input.setText(this.input.getText() + listen);
        }
        this.bigWork(listen);
    }


    /*****************************************状态**************************************************/

    // 小数点信号
    private Boolean pointSignal = false;
    // 括号信号
    private int barcketNum = 0;

    private String num = "0123456789";
    private String sign = "+-x/(";

    // 输入的最后一位为数字时的状态,详细见详细设计表格
    public void inNum() {
        // 只能输入pow函数,右括号,数字和符号按钮,不能输入左括号,若小数点信号为真,则可以输入小数点
        for (int i=0;i<20;i++) {
            if("(".equals(this.cal[i].getText())) {
                this.cal[i].setEnabled(false);
            }
            else {
                this.cal[i].setEnabled(true);
            }
        }
        // 根据信号设置
        this.cal[17].setEnabled(this.pointSignal);
    }

    // 输入的最后一位为符号或左括号时
    public void inSign() {
        // 只能输入非小数点数字及左括号,小数点信号开启
        for (int i=0;i<20;i++) {
            if("(".equals(this.cal[i].getText()) || this.num.contains(this.cal[i].getText())) {
                this.cal[i].setEnabled(true);
            }
            else {
                this.cal[i].setEnabled(false);
            }
        }
        this.pointSignal = true;
    }

    // 输入最后一位为右括号或pow运算时
    public void inPow() {
        // 只能输入符号和右括号和pow函数
        for (int i=0;i<20;i++) {
            if("(".equals(this.cal[i].getText()) || this.num.contains(this.cal[i].getText()) || ".".equals(this.cal[i].getText())) {
                this.cal[i].setEnabled(false);
            }
            else {
                this.cal[i].setEnabled(true);
            }
        }
    }

    // 输入最后一位为小数点时
    public void inPoint() {
        // 只能输入非小数点数字,小数点信号关闭
        for (int i=0;i<20;i++) {
            if(this.num.contains(this.cal[i].getText())) {
                this.cal[i].setEnabled(true);
            }
            else {
                this.cal[i].setEnabled(false);
            }
        }
        this.pointSignal = false;
    }

    public void inEqual() {
        for (int i=0;i<20;i++) {
            this.cal[i].setEnabled(false);
        }
    }


    /*****************************************核酸隔离点*********************************************/


    // 真正的超级初始化块
    public calculator() throws HeadlessException {
        // 界面设置
        this.__init__();
        this.setNorth();
        this.setCenter();
        this.setSouth();
        // 交互设置
        this.setListener();
        JOptionPane.showMessageDialog(this, "由于框架原因,本计算器打开时可能按钮显示不全,请最小化后打开");
        this.inSign();
        this.calculate.refresh();
    }


    calculate calculate = new calculate();
    private String temStr = "";

    // 记录公式及答案为后续拓展提供api
    private String caled;
    private String ans;

    public void setCaled(String caled) {
        this.caled = caled;
    }

    public void setAns(BigDecimal ans) {
        this.ans = ans.toString();
    }

    public String getCaled() {
        return caled;
    }

    public String getAns() {
        return ans;
    }

    // 控制器
    public void bigWork(String listen) {
        
        // 记录括号信号
        if ("(".equals(listen)) {
            this.barcketNum++;
        }
        if (")".equals(listen)) {
            this.barcketNum--;
        }
        
        // 基础状体转换
        if (this.num.contains(listen)) {
            this.temStr = this.temStr +listen;
            this.inNum();
        } else if (this.sign.contains(listen)) {
            if(!"".equals(temStr)) {
                this.calculate.numPush(this.temStr);
                this.temStr = "";
            }
            this.calculate.calIOC(listen);
            this.inSign();
        } else if (")".equals(listen) || listen.contains("^")) {
            if(!"".equals(temStr)) {
                this.calculate.numPush(this.temStr);
                this.temStr = "";
            }
            if (listen.contains("^")) {
                calculate.powIOC(listen);
            } else {
                this.calculate.barcketIOC();
            }
            this.inPow();
        } else if (".".equals(listen)) {
            this.temStr = this.temStr +listen;
            this.inPoint();
        }  else if ("=".equals(listen)) {
            if(!"".equals(temStr)) {
                this.calculate.numPush(this.temStr);
                this.temStr = "";
            }
            this.setCaled(this.input.getText());
            this.setAns(this.calculate.equaIOC());
            con.openMySql();
            String insertSql = "INSERT INTO usercalcu VALUES ('" + user + "','" + caled + "'," + ans + ")";
            con.update(insertSql);
            this.input.setText(this.ans);
            this.inEqual();
        }else if ("C".equals(listen)) {
            this.calculate.refresh();
            this.input.setText("");
            this.temStr = "";
            this.barcketNum = 0;
            this.inSign();
        } else {
            JOptionPane.showMessageDialog(this, "error : unvaild input");
        }
        
        // 限制用户输入
        if (this.barcketNum < 0) {
            JOptionPane.showMessageDialog(this,"error : wrong number of barcket");
        }
        if(this.barcketNum == 0) {
            this.cal[3].setEnabled(false);
        }

        if (this.barcketNum > 0) {
            this.cal[18].setEnabled(false);
        }
    }

    public calculator(String uname) throws HeadlessException{
        // 界面设置
        this.__init__();
        this.setNorth();
        this.setCenter();
        // 获取uname
        this.setUser(uname);
        this.setSouth();
        // 交互设置
        this.setListener();
        JOptionPane.showMessageDialog(this, "由于框架原因,本计算器打开时可能按钮显示不全,请最小化后打开");
        this.inSign();
        this.calculate.refresh();
    }



    // 软件测试


}
复制代码

数据库代码

 

复制代码
package calculator;

import java.sql.*;
public class connectionMySql {
    Connection con = null;
    ResultSet  res = null;
    //打开数据库链接
    public Connection openMySql(){
        try{
            //bc链接MySQL数据库
            //加载注册驱动
            Class.forName("com.mysql.jdbc.Driver");
            //连接数据库
            String ulr="jdbc:mysql://127.0.0.1:3306/user?characterEncoding=UTF-8";
            String uname="root";
            String upass="030605bbb";
            con = DriverManager.getConnection(ulr, uname, upass);
        }catch(Exception e){
            e.printStackTrace();
        }
        if(con == null){
            System.out.println("链接失败");
        }
        else{
            System.out.println("链接成功");
        }
        return con;
    }

    //增删改操作
    public int update(String sql){
        //保存返回值
        int re =0;
        try{
            Statement sta = con.createStatement();
            re=sta.executeUpdate(sql);
        }catch(Exception e){
            e.printStackTrace();
        }
        return re;
    }

    //查询值
    public ResultSet select(String sql){
        try{
            Statement sta = con.createStatement();
            res=sta.executeQuery(sql);
        }catch(Exception e){
            e.printStackTrace();
        }
        return res;
    }
    //破解表结构
    public void passTable(String tablename) {
        try {
            Statement sta = con.createStatement();
            String selectsql="select * from "+tablename;
            ResultSet res = sta.executeQuery(selectsql);
            ResultSetMetaData meta = res.getMetaData();
            int sum = meta.getColumnCount();
            for(int i=1;i<=sum;i++){
                //获取对应的字段名
                String name=meta.getColumnName(i);
                //获取对应的字段类型
                String columtype=meta.getColumnTypeName(i);//类型名底层类型为int
                System.out.println(name+":"+columtype);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
复制代码

 

 

 

四、实例

注册一个账户,id 123456, 密码 123456

 

 登录这个账户

 

 

计算7+7=14

 

 数据库中储存信息

 

 

posted @   bought  阅读(76)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示