第二次作业

一、实验目的

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

2.掌握软件设计和开发的基本工具。

3.理解集成软件开发环境在软件开发过程中的作用。

4.模拟计算器的功能,对数据进行加减乘除以及开方运算并可保存历史计算记录。

二、实验要求

1.完成计算器软件的UI设计、使用Visio设计计算器软件中所涉及的流程图。

2.选择合适的集成开发环境和工具完成计算器软件的开发和功能测试。

3.自己设计登录页面并和简易计算器连接并将数据保存在数据库中。

三、实验环境

1.操作系统:Windows11

2.开发测试工具:IDEA编写登录界面以及计算器相关代码,连接MySQL数据库存储计算记录。

3.流程图:visio

四、基本功能描述

一、相关功能

简易计算器包括基本的四则运算(加、减、乘、除)及开方运算并可存储历史计算数据功能。

二、JDBC相关介绍

JDBC核心接口与类:JDBC核心类库包含在java.sql包中。

接口:(1)Connection:特定数据库的连接(会话)。在连接上下文中执行SQL语句并返回结果。(2)PreparedStatement:表示预编译的 SQL 语句的对象。(3)Statement:用于执行静态 SQL 语句并返回它所生成结果的对象。(4)ResultSet :表示数据库结果集的数据表,通常通过执行查询数据库的语句生成 。(5)CallableStatement :用于执行 SQL存储过程的接口 。

类:(1)DriverManager:负责管理JDBC驱动程序。使用JDBC驱动程序之前,必须先将驱动程序加载并注册后才可以使用,同时提供方法来建立与数据库的连接。(2)SQLException:有关数据库操作的异常

五、软件设计

1、登录界面设计

(1)流程图

(2)登录代码

package login;

import javax.swing.*;

 

import jisuanqi.Calculator;

 

import java.awt.*;

import java.awt.event.*;

 

public class Login extends JFrame {

    private JTextField usernameField;

    private JPasswordField passwordField;

    private JButton loginButton;

    private JButton registerButton;

 

    public Login() {

        // 设置窗口标题

        setTitle("用户登录注册");

 

        // 设置窗口大小

        setSize(500,300);

 

        // 设置窗口可调整大小

        setResizable(true);

 

        // 设置关闭窗口时的默认操作

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

 

        // 创建用户名和密码输入框

        usernameField = new JTextField(20);

        passwordField = new JPasswordField(20);

 

        // 创建登录和注册按钮

        loginButton = new JButton("登录");

        registerButton = new JButton("注册");

       

 

 

        // 创建容器并设置布局管理器

        Container container = getContentPane();

        container.setLayout(new FlowLayout());

       

        // 添加组件到容器中

        container.setLayout(new GridLayout(3, 2)); // 设置网格布局,2行2列

 

        container.add(new JLabel("用户名:"));

        container.add(usernameField);

        container.add(new JLabel("密码:"));

        container.add(passwordField);

        container.add(loginButton);

        container.add(registerButton);

 

        // 为登录按钮添加事件监听器

        loginButton.addActionListener(new ActionListener() {

            @Override

            public void actionPerformed(ActionEvent e) {

                // 进行登录逻辑处理

                if (validateLogin()) {

                    // 登录成功后打开计算器界面

                    openCalculator();

                } else {

                    JOptionPane.showMessageDialog(null, "用户名或密码错误", "登录失败", JOptionPane.ERROR_MESSAGE);

                }

            }

        });

 

        // 为注册按钮添加事件监听器

        registerButton.addActionListener(new ActionListener() {

            //@Override

            public void actionPerformed(ActionEvent e) {

                // 进行注册逻辑处理

                if (validateRegister()) {

                    JOptionPane.showMessageDialog(null, "用户注册成功", "注册成功", JOptionPane.INFORMATION_MESSAGE);

                } else {

                    JOptionPane.showMessageDialog(null, "用户名已存在", "注册失败", JOptionPane.ERROR_MESSAGE);

                }

            }

        });

    }

    private boolean validateLogin() {

        // 实现登录验证逻辑

        String username = usernameField.getText();

        String password = new String(passwordField.getPassword());

 

        // 假设正确的用户名是"l12345678",密码是“123456”

        return "l12345678".equals(username) && "123456".equals(password);

    }

 

    private boolean validateRegister() {

        // 实现注册验证逻辑

        String username = usernameField.getText();

        

        // 假设用户名不能重复,新用户注册时检查用户名是否已存在

        // 这里简单地假设已存在一个用户"l12345678"

        return !"l12345678".equals(username);

    }

 

    private void openCalculator() {

        // 打开计算器界面

        Calculator calculator = new Calculator();

        calculator.setVisible(true);

 

    }

  public static void main(String[] args) {

        // 在主线程中创建并显示登录注册界面

        SwingUtilities.invokeLater(new Runnable() {

            public void run() {

                Login frame = new Login();

                frame.setVisible(true);

            }

        });

    }

}

(3)运行完成后界面显示

用户名和密码都正确,点击登录打开计算器界面进行计算

注册

2、计算器设计

1)计算器流程图

2)代码

package jisuanqi;

import java.awt.*;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import java.util.Objects;

 

import javax.swing.*;

 

//Calculator类,继承JFrame框架,实现事件监听器接口

public class Calculator extends JFrame implements ActionListener {

  private final String[] KEYS = { "sqrt","(", ")","AC","7", "8", "9", "÷" ,"4", "5", "6", "*", "1", "2", "3", "+", "0", "-",

            "x*x", "=" };

    private JButton keys[] = new JButton[KEYS.length];

    private JTextArea resultText = new JTextArea("0.0");// 文本域组件TextArea可容纳多行文本;文本框内容初始值设为0.0

    private JTextArea History = new JTextArea();// 历史记录文本框初始值设为空

    private JPanel jp2=new JPanel();

    private JScrollPane gdt1=new JScrollPane(resultText);//给输入显示屏文本域新建一个垂直滚动滑条

    private JScrollPane gdt2=new JScrollPane(History);//给历史记录文本域新建一个垂直滚动滑条

    private JScrollPane gdt3=new JScrollPane(History);//给历史记录文本域新建一个水平滚动滑条

    private JLabel label = new JLabel("历史记录");

    private String b = "";

 

    // 构造方法

    public Calculator() {

        super("Caculator");//“超”关键字,表示调用父类的构造函数,

        resultText.setBounds(20, 18, 255, 115);// 设置文本框大小

        resultText.setAlignmentX(RIGHT_ALIGNMENT);// 文本框内容右对齐

        resultText.setEditable(false);// 文本框不允许修改结果

        History.setBounds(290, 40, 250,370);// 设置文本框大小

        History.setAlignmentX(LEFT_ALIGNMENT);// 文本框内容右对齐

        History.setEditable(false);// 文本框不允许修改结果

        label.setBounds(300, 15, 100, 20);//设置标签位置及大小

        jp2.setBounds(290,40,250,370);//设置面板窗口位置及大小

        jp2.setLayout(new GridLayout());

        JPanel jp1 = new JPanel();

        jp1.setBounds(20,18,255,115);//设置面板窗口位置及大小

        jp1.setLayout(new GridLayout());

        resultText.setLineWrap(true);// 激活自动换行功能

        resultText.setWrapStyleWord(true);// 激活断行不断字功能

        resultText.setSelectedTextColor(Color.RED);

        History.setLineWrap(true);//自动换行

        History.setWrapStyleWord(true);

        History.setSelectedTextColor(Color.blue);

        gdt1.setViewportView(resultText);//使滚动条显示出来

        gdt2.setViewportView(History);

        gdt1.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);//设置让垂直滚动条一直显示

        gdt2.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);//设置让垂直滚动条一直显示

        gdt2.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);//设置让水平滚动条一直显示

        jp1.add(gdt1);//将滚动条添加入面板窗口中

        jp2.add(gdt2);

        this.add(jp1);//将面板添加到总窗体中

        this.add(jp2);//将面板添加到总窗体中

        this.setLayout(null);

        this.add(label);// 新建“历史记录”标签

        

        // 放置按钮

        int x = 20, y = 150;

        for (int i = 0; i < KEYS.length; i++)

        {

            keys[i] = new JButton();

            keys[i].setText(KEYS[i]);

            keys[i].setBounds(x, y, 60, 40);

            if (x < 215) {

                x += 65;

            } else {

                x = 20;

                y += 45;

            }

            this.add(keys[i]);

        }

        for (int i = 0; i < KEYS.length; i++)// 每个按钮都注册事件监听器

        {

            keys[i].addActionListener(this);

        }

        this.setResizable(false);

        this.setBounds(500, 200, 567, 480);

        this.setDefaultCloseOperation(EXIT_ON_CLOSE);

        this.setVisible(true);

    }

   // 事件处理

    public void actionPerformed(ActionEvent e)

    {

        String label=e.getActionCommand();//获得事件源的标签

        if(Objects.equals(label, "="))//

        {

            resultText.setText(this.b);

            History.setText(History.getText()+resultText.getText());

 

if(label.equals("="))//调用计算方法,得出最终结果

            {

                String[] s =houzhui(this.b);

                String result=Result(s);

                this.b=result+"";

                //更新文本框,当前结果在字符串b中,并未删除,下一次输入接着此结果以实现连续运算

                resultText.setText(this.b);

                History.setText(History.getText()+"="+resultText.getText()+"\n");

            }

        }

        else if(Objects.equals(label, "AC"))//清空按钮,消除显示屏文本框前面所有的输入和结果

        {

            this.b="";

            resultText.setText("0");//更新文本域的显示,显示初始值;

        }

        else if(Objects.equals(label, "sqrt"))

        {

            String n=kfys(this.b);

            resultText.setText("sqrt"+"("+this.b+")"+"="+n);//使运算表达式显示在输入界面

            History.setText(History.getText()+"sqrt"+"("+this.b+")"+"=");//获取输入界面的运算表达式并使其显示在历史记录文本框

            this.b=n;

        }

        else if(Objects.equals(label, "x*x"))

        {

            String m=pfys(this.b);

            resultText.setText(this.b+"^2"+"="+m);//使运算表达式显示在输入界面

            History.setText(History.getText()+this.b+"^2"+"=");//获取输入界面的运算表达式并使其显示在历史记录文本框

            this.b=m;

        }

       

        else

        {

            this.b=this.b+label;

            resultText.setText(this.b);

 

        }

    }

    //将中缀表达式转换为后缀表达式

    private String[] houzhui(String str) {

        String s = "";// 用于承接多位数的字符串

        char[] opStack = new char[100];// 静态栈,对用户输入的操作符进行处理,用于存储运算符

        String[] postQueue = new String[100];// 后缀表达式字符串数组,为了将多位数存储为独立的字符串

        int top = -1, j = 0;// 静态指针top,控制变量j

        for (int i = 0; i < str.length(); i++)// 遍历中缀表达式

        // indexof函数,返回字串首次出现的位置;charAt函数返回index位置处的字符;

        {

            if ("0123456789.".indexOf(str.charAt(i)) >= 0) // 遇到数字字符的情况直接入队

            {

                s = "";// 作为承接字符,每次开始时都要清空

                for (; i < str.length() && "0123456789.".indexOf(str.charAt(i)) >= 0; i++) {

                    s = s + str.charAt(i);

                    //比如,中缀表达式:234+4*2,我们扫描这个字符串的时候,s的作用相当于用来存储长度为3个字符的操作数:234

                }

                i--;

                postQueue[j] = s;// 数字字符直接加入后缀表达式

                j++;

            }

            else if ("(".indexOf(str.charAt(i)) >= 0) {// 遇到左括号

                top++;

                opStack[top] = str.charAt(i);// 左括号入栈

            }

            else if (")".indexOf(str.charAt(i)) >= 0) {// 遇到右括号

                for (;;)// 栈顶元素循环出栈,直到遇到左括号为止

                {

                    if (opStack[top] != '(') {// 栈顶元素不是左括号

                        postQueue[j] = opStack[top] + "";// 栈顶元素出栈

                        j++;

                        top--;

                    } else { // 找到栈顶元素是左括号

                        top--;// 删除栈顶左括号

                        break;// 循环结束

                    }

                }

            }

            else if ("*÷+-".indexOf(str.charAt(i)) >= 0)// 遇到运算符

            {

                if (top == -1)

                 {// 若栈为空则直接入栈

                    top++;

                    opStack[top] = str.charAt(i);

                }

                else if ("*÷".indexOf(opStack[top]) >= 0)

                {// 当栈顶元素为高优先级运算符时,让栈顶元素出栈进入后缀表达式后,当前运算符再入栈

                        postQueue[j] = opStack[top] + "";

                        j++;

                    opStack[top] = str.charAt(i);

                }

                else 

                {

                    top++;

                    opStack[top] = str.charAt(i);// 当前元素入栈

                }

            }

        }

        while (top != -1) {// 遍历结束后将栈中剩余元素依次出栈进入后缀表达式

            postQueue[j] = opStack[top] + "";

            j++;

            top--;

        }

        return postQueue;

    }

     //开方运算方法

    public String kfys(String str) {

        String result = "";

 

        double a = Double.parseDouble(str), b = 0;

        b = Math.sqrt(a);

        result = String.valueOf(b);//将运算结果转换为string类型并赋给string类型的变量result

        return result;

    }

 

    //平方运算方法

    public String pfys(String str) {

        String result = "";

        double a = Double.parseDouble(str), b = 0;

        b = Math.pow(a, 2);

        result = String.valueOf(b);

        return result;

    }

 

    // 计算后缀表达式,并返回最终结果

    public String Result(String[] str) {

        String[] Result = new String[100];// 顺序存储的栈,数据类型为字符串

        int Top = -1;// 静态指针Top

        for (int i = 0; str[i] != null; i++) {

            if ("+-*÷".indexOf(str[i]) < 0) {  //遇到数字,直接入栈

                Top++;

                Result[Top] = str[i];

            }

            if ("+-*÷".indexOf(str[i]) >= 0)// 遇到运算符字符,将栈顶两个元素出栈计算并将结果返回栈顶

            {

                double x, y, n;

                x = Double.parseDouble(Result[Top]);// 顺序出栈两个数字字符串,并转换为double类型

                Top--;

                y = Double.parseDouble(Result[Top]);

                Top--;

                if ("*".indexOf(str[i]) >= 0) {

                    n = y * x;

                    Top++;

                    Result[Top] = String.valueOf(n);// 将运算结果重新入栈

 

                }

                if ("÷".indexOf(str[i]) >= 0)

                {

                    if (x == 0)// 被除数不允许为0

                    {

                        String s = "error!";

                        return s;

                    } else {

                        n = y / x;

                        Top++;

                        Result[Top] = String.valueOf(n);// 将运算结果重新入栈

                    }

                }

                

                if ("-".indexOf(str[i]) >= 0) {

                    n = y - x;

                    Top++;

                    Result[Top] = String.valueOf(n);// 将运算结果重新入栈

                }

                if ("+".indexOf(str[i]) >= 0) {

                    n = y + x;

                    Top++;

                    Result[Top] = String.valueOf(n);// 将运算结果重新入栈

                }

            }

        }

        return Result[Top];// 返回最终结果

    }

 

    // 主函数

    public static void main(String[] args) {

        Calculator a = new Calculator();

    }

}

(3)功能测试

(1)加法;用户计算完后可点击AC键将计算框清零也可继续计算

(2)减法;用户计算完后可点击AC键将计算框清零也可继续计算

(3)乘法;用户计算完后可点击AC键将计算框清零也可继续计算

(4)除法用户计算完后可点击AC键将计算框清零也可继续计算

除法中除数不能为零,为零时报错

3、连接数据库将结果保存在数据库中

(1)代码

package com.jilu.domian;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

public class MySQLConnection {
    public static void main(String[] args) {
        // 数据库连接信息
        String url = "jdbc:mysql://localhost:3306/test?characterEncoding=UTF-8";
        String user = "root";
        String password = "123456";
        try {
            // 加载数据库驱动
            Class.forName("com.mysql.jdbc.Driver");
            // 建立数据库连接
            Connection connection = DriverManager.getConnection(url, user, password);
            // 创建Statement对象
            Statement statement = connection.createStatement();
            // 增加数据
            String insertQuery = "INSERT INTO history (a, b) VALUES ('value1', 'value2')";
            statement.executeUpdate(insertQuery);
            // 删除数据
            String deleteQuery = "DELETE FROM history WHERE a = 'value1'";
            statement.executeUpdate(deleteQuery);
            // 修改数据
            String updateQuery = "UPDATE history SET b = 'newvalue' WHERE a = 'value1'";
            statement.executeUpdate(updateQuery);
            // 关闭连接
            statement.close();
            connection.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

(2)结果:

建立表

连接数据库

保存数据

 

posted @ 2023-12-03 22:23  吝佳妮  阅读(46)  评论(0)    收藏  举报