[实验目的]
1.掌握软件开发的基本流程
2.掌握常用的软件开发方式和工具。
[实验内容]
设计一个包含登录界面的计算器软件,该软件可以实现第一次作业中的全部功能,同时可以保存用户的历史计算记录(保存数据最好使用数据库)。
[实验环境及开发工具]
- 使用Microsoft Visio作绘图工具
- 使用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;
}
}
三、结果分析
-
计算器功能:
- 计算器支持基本的算术运算(+,-,*,/),平方根(√)和退格功能。
- 它使用简单的表达式评估方法来计算结果。
-
图形用户界面(GUI):
- 使用Swing组件创建了GUI,提供了用户友好的界面。
- 计算器布局包括数字按钮,运算符按钮以及用于特殊功能的其他按钮。
-
用户登录:
- 提供了一个基本的登录面板,用户可以输入用户名和密码。
- 登录功能很基础,仅供演示目的,使用了单个预定义用户的硬编码用户名和密码。
-
历史记录跟踪:
- 计算器维护已登录用户的计算历史。
- 历史记录存储在
ArrayList<String>
中,可以通过使用JDBC连接到数据库并保存历史记录来保存它们。
-
数据库连接(示例):
- 代码包括一个基本示例,演示了如何连接到MySQL数据库并保存计算历史记录。
- 使用JDBC建立连接,准备SQL语句并执行它们以将历史记录插入数据库。
-
代码结构:
- 代码按照方法和类进行组织,以提高可读性和可维护性。
- 使用Java 8中引入的lambda表达式进行事件处理。
-
改进和注意事项:
- 登录功能很基础,不适用于实际应用。在生产环境中,应实施更安全的身份验证机制,例如使用哈希密码和适当的用户管理。
- 数据库连接代码比较简单。在实际应用中,您可能会使用连接池,更有效地处理异常,并可能使用ORM(对象关系映射)库。
- 计算器的表达式评估有限。为了更强大的解决方案,您可能考虑使用类似于Apache Commons Math的库。
-
用户界面注意事项:
- GUI布局很简单,但根据用户期望,您可能会考虑改进或添加更全面的计算器功能。
请记住,这个分析基于提供的代码,根据具体要求和用例,可能需要进一步改进或修改。