基于java做一个登录页面及其数据保存的计算器

发布时间 2023-12-05 01:06:42作者: renzixin

[实验目的]

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

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

[实验内容]

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

[实验环境及开发工具]

  1. 使用Microsoft Visio作绘图工具
  2. 使用Java语言与IntelliJ IDEA Community Edition作开发工具

一、登录页面

1.程序流程图

 

 

2测试截图

1.登录页面

 

2.必须先输入账号密码

3.账号密码必须输入正确

4.登陆成功,正常使用页面

5.记录页面

 

 

 

、代码部分

import javax.swing.*;

import java.awt.*;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import java.util.ArrayList;

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.PreparedStatement;

import java.sql.SQLException;

 

public class CalculatorApp {

 

    private JFrame frame;

    private JTextField displayField;

    private String currentInput = "";

    private ArrayList<String> history = new ArrayList<>();

    private User currentUser; // 当前登录的用户

 

    public static void main(String[] args) {

        SwingUtilities.invokeLater(() -> {

            try {

                CalculatorApp window = new CalculatorApp();

                window.frame.setVisible(true);

            } catch (Exception e) {

                e.printStackTrace();

            }

        });

    }

 

    public CalculatorApp() {

        initialize();

    }

 

    private void initialize() {

        frame = new JFrame();

        frame.setBounds(100, 100, 400, 400);

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.getContentPane().setLayout(new BorderLayout());

 

        displayField = new JTextField();

        displayField.setEditable(false);

        frame.getContentPane().add(displayField, BorderLayout.NORTH);

 

        JPanel buttonPanel = new JPanel();

        buttonPanel.setLayout(new GridLayout(5, 4));  // Adjusted for the square root button

 

        String[] buttonLabels = {

                "7", "8", "9", "/",

                "4", "5", "6", "*",

                "1", "2", "3", "+",

                "0", ".", "sqrt","-", // Updated for square root and backspace

                "=", "<-",

        };

 

        for (String label : buttonLabels) {

            JButton button = new JButton(label);

            button.addActionListener(new ButtonClickListener());

            buttonPanel.add(button);

        }

 

        frame.getContentPane().add(buttonPanel, BorderLayout.CENTER);

 

        JButton clearButton = new JButton("C");

        clearButton.addActionListener(new ActionListener() {

            @Override

            public void actionPerformed(ActionEvent e) {

                clearDisplay();

            }

        });

        frame.getContentPane().add(clearButton, BorderLayout.SOUTH);

 

        // 添加登录界面

        addLoginPanel();

    }

 

    private void addLoginPanel() {

        JPanel loginPanel = new JPanel();

        loginPanel.setLayout(new GridLayout(3, 2));

 

        JTextField usernameField = new JTextField();

        JPasswordField passwordField = new JPasswordField();

 

        loginPanel.add(new JLabel("Username:"));

        loginPanel.add(usernameField);

        loginPanel.add(new JLabel("Password:"));

        loginPanel.add(passwordField);

 

        JButton loginButton = new JButton("Login");

        loginButton.addActionListener(new ActionListener() {

            @Override

            public void actionPerformed(ActionEvent e) {

                String username = usernameField.getText();

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

 

                // TODO: 这里可以添加用户验证逻辑,例如检查用户名和密码是否匹配

                // 在实际应用中,可以使用数据库或其他方式来验证用户

 

                // 示例:假设只有一个预定义用户

                User user = new User("user", "1234567");

 

                if (username.equals(user.getUsername()) && password.equals(user.getPassword())) {

                    currentUser = user;

                    JOptionPane.showMessageDialog(frame, "Login successful!");

                } else {

                    JOptionPane.showMessageDialog(frame, "Invalid username or password");

                }

            }

        });

 

        frame.getContentPane().add(loginPanel, BorderLayout.WEST);

        frame.getContentPane().add(loginButton, BorderLayout.SOUTH);

    }

 

    private void clearDisplay() {

        if (!currentInput.isEmpty()) {

            currentInput = currentInput.substring(0, currentInput.length() - 1);

            updateDisplay();

        }

    }

 

    private void updateDisplay() {

        displayField.setText(currentInput);

    }

 

    private class ButtonClickListener implements ActionListener {

        public void actionPerformed(ActionEvent e) {

            // 检查用户是否已登录

            if (currentUser == null) {

                JOptionPane.showMessageDialog(frame, "Please login first.");

                return;

            }

 

            JButton source = (JButton) e.getSource();

            String buttonText = source.getText();

 

            if ("0123456789.".contains(buttonText)) {

                currentInput += buttonText;

            } else if ("+-*/".contains(buttonText)) {

                currentInput += " " + buttonText + " ";

            } else if ("=".equals(buttonText)) {

                try {

                    String result = evaluateExpression();

                    history.add(currentInput + " = " + result);

                    saveHistory(); // 保存历史记录

                    clearDisplay();

                    currentInput = result;

                } catch (ArithmeticException ex) {

                    clearDisplay();

                    currentInput = "Error";

                }

            } else if ("C".equals(buttonText)) { // Clear Entry (Backspace) functionality

                clearDisplay();

            } else if ("sqrt".equals(buttonText)) {

                try {

                    double operand = Double.parseDouble(currentInput);

                    currentInput = String.valueOf(Math.sqrt(operand));

                } catch (NumberFormatException ex) {

                    clearDisplay();

                    currentInput = "Error";

                }

            } else if ("<-".equals(buttonText)) {

                clearDisplay();

            }

 

            updateDisplay();

        }

 

       private void saveHistory() {

        try {

        // Establish a database connection

        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/your_database", "root", "1022renzixin");

 

        // Prepare a SQL statement for insertion

        PreparedStatement statement = connection.prepareStatement("INSERT INTO history (expression, result, user_id) VALUES (?, ?, ?)");

 

        // Iterate through history and save records

        for (String record : history) {

        String[] parts = record.split(" = ");

        String expression = parts[0];

        String result = parts[1];

 

        // Set values for the prepared statement

        statement.setString(1, user);

        statement.setString(2,expression);

        statement.setInt(3,  result);        

        statement.executeUpdate();

        }

 

        // Close resources

        statement.close();

        connection.close();

        } catch (SQLException e) {

        e.printStackTrace();

        }

        }

 

        }

 

        private String evaluateExpression() throws ArithmeticException {

            String[] tokens = currentInput.split(" ");

            double operand1 = Double.parseDouble(tokens[0]);

            String operator = tokens[1];

            double operand2 = Double.parseDouble(tokens[2]);

 

            switch (operator) {

                case "+":

                    return String.valueOf(operand1 + operand2);

                case "-":

                    return String.valueOf(operand1 - operand2);

                case "*":

                    return String.valueOf(operand1 * operand2);

                case "/":

                    if (operand2 == 0) {

                        throw new ArithmeticException("Cannot divide by zero");

                    }

                    return String.valueOf(operand1 / operand2);

                default:

                    return "Error";

            }

        }

 

    }

}

 

 

// 新增User

class User {

    private String username;

    private String password;

 

    public User(String username, String password) {

        this.username = username;

        this.password = password;

    }

 

    public String getUsername() {

        return username;

    }

 

    public String getPassword() {

        return password;

    }

}

 三、结果分析

  1. 计算器功能:

    • 计算器支持基本的算术运算(+,-,*,/),平方根(√)和退格功能。
    • 它使用简单的表达式评估方法来计算结果。
  2. 图形用户界面(GUI):

    • 使用Swing组件创建了GUI,提供了用户友好的界面。
    • 计算器布局包括数字按钮,运算符按钮以及用于特殊功能的其他按钮。
  3. 用户登录:

    • 提供了一个基本的登录面板,用户可以输入用户名和密码。
    • 登录功能很基础,仅供演示目的,使用了单个预定义用户的硬编码用户名和密码。
  4. 历史记录跟踪:

    • 计算器维护已登录用户的计算历史。
    • 历史记录存储在ArrayList<String>中,可以通过使用JDBC连接到数据库并保存历史记录来保存它们。
  5. 数据库连接(示例):

    • 代码包括一个基本示例,演示了如何连接到MySQL数据库并保存计算历史记录。
    • 使用JDBC建立连接,准备SQL语句并执行它们以将历史记录插入数据库。
  6. 代码结构:

    • 代码按照方法和类进行组织,以提高可读性和可维护性。
    • 使用Java 8中引入的lambda表达式进行事件处理。
  7. 改进和注意事项:

    • 登录功能很基础,不适用于实际应用。在生产环境中,应实施更安全的身份验证机制,例如使用哈希密码和适当的用户管理。
    • 数据库连接代码比较简单。在实际应用中,您可能会使用连接池,更有效地处理异常,并可能使用ORM(对象关系映射)库。
    • 计算器的表达式评估有限。为了更强大的解决方案,您可能考虑使用类似于Apache Commons Math的库。
  8. 用户界面注意事项:

    • GUI布局很简单,但根据用户期望,您可能会考虑改进或添加更全面的计算器功能。

请记住,这个分析基于提供的代码,根据具体要求和用例,可能需要进一步改进或修改。