第二次作业
实验:计算器Java程序
班级:21计科1班 狄学芳
一、实验目的
基于Java语言开发一种具备多种运算功能和历史记录功能的计算器登录界面。该计算器应该能够实现基本的加减乘除运算功能,同时具备算术开方功能和历史记录功能。用户可以通过输入用户名和密码进入计算器界面,并且可以将历史记录保存到数据库中。本文对计算器登录界面的设计、实现及数据库连接等方面进行了详细的阐述,并给出了部分代码示例。
二、实验内容
设计了一个登录界面,登录成功后会跳转到计算器界面,该计算器能够实现上次作业中的所有功能,在程序运行过程中,我们还连接了数据库,实现了计算器数据的存储和读取。为了方便用户查看和记录计算过程,我们实现了历史记录功能,将计算器里的历史记录存储到数据库中。
三、实验步骤
1、 创建登录界面:使用HTML创建一个登录界面,并且利用css(样式),JavaScript(用于交互) 等创建的登陆界面和重置密码界面。
2、 创建计算器界面:使用swing库创建计算器界面,为每个按钮添加事件监听器,以便执行相应的功能。
3、 连接sqlyog数据库:在计算器界面中,添加一个按钮用于保存历史记录到sqlyog数据库中,为该按钮添加事件监听器;在登录界面中同样将用户信息保存在数据库中,以便登录。
4、 运行项目:运行计算器项目,并在计算器界面中进行计算。当用户点击“等于”按钮时,计算器会将当前的操作,操作数和结果保存到sqlyog数据库中。
四、功能页面设计
1、 登录界面和计算器界面程序流程图
图1.1登录界面程序流程图
图1.2计算器界面程序流程图
图1.3连接数据库所用的类和接口
3、登陆界面
初始界面:
当信息没有输完整时
当用户名不存在时
当输入的密码错误时
当用户点击忘记密码
重置时用户名不存在界面
重置的新密码和确认密码不一致时
重置密码成功时
创建成功登录系统的数据库
连接数据库
创建数据库和表
计算器界面
1、2+3=5.0
2、43-21=22.0
3、32/4=8.0
4、43*32.6=1401.8
5、√4=2
数据库中的历史记录
五、实验代码
1、登录界面数据,若登录成功就会跳转到计算器界面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>登录页面</title>
<style>
body {
font-family: Arial, Helvetica, sans-serif;
background-image: url('background1.jpg'); /* 添加背景图 */
background-size: cover;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
padding: 0;
}
#loginBox {
background-color: #ffffff;
width: 400px;
padding: 20px;
border-radius: 5px;
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.2);
}
input[type=text],
input[type=password] {
width: 100%;
padding: 12px 20px;
margin: 8px 0;
display: inline-block;
border: 1px solid #ccc;
border-radius: 4px;
box-sizing: border-box;
}
button {
background-color: #4CAF50;
color: white;
padding: 14px 20px;
margin: 8px 0;
border: none;
border-radius: 4px;
cursor: pointer;
width: 100%;
}
button:hover {
background-color: #45a049;
}
.error-msg {
color: rgb(195, 0, 0);
font-size: 14px;
margin-bottom: 10px;
text-align: center;
}
</style>
</head>
<body>
<div id="loginBox">
<h1 style="text-align: center;">用户登录</h1>
<form action="other-page.html" method="POST">
<label for="username">用户名</label>
<input type="text" id="username" name="username" placeholder="请输入用户名" required>
<label for="password">密码</label>
<input type="password" id="password" name="password" placeholder="请输入密码" required>
<div class="error-msg" id="errorMsg"></div>
<button type="submit">登录</button>
<a href="other-page1.html" style="text-decoration: none; display: block; text-align: center; margin-top: 10px;">忘记密码?</a>
</form>
</div>
<script>
const users = {
"西二": "123",
"李四": "123",
"安": "1234"
};
const form = document.querySelector('form');
const errorMsg = document.getElementById('errorMsg');
form.addEventListener('submit', function(event) {
event.preventDefault();
// 获取用户输入的用户名和密码
const username = form.elements.username.value.trim();
const password = form.elements.password.value.trim();
// 验证用户名和密码
if (users[username] && users[username] === password) {
window.location.href = 'calculator.html'; // 将页面重定向到计算器页面
} else if (users[username] && users[username] !== password) {
errorMsg.innerText = '密码错误';
} else {
errorMsg.innerText = '用户名不存在';
}
});
</script>
</body>
</html>
重置界面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>重置密码</title>
<style>
body {
font-family: Arial, Helvetica, sans-serif;
background-image: url('background1.jpg'); /* 添加背景图 */ display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
padding: 0;
}
#resetBox {
background-color: white;
width: 400px;
padding: 20px;
border-radius: 5px;
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.2);
}
input[type=text],
input[type=password] {
width: 100%;
padding: 12px 20px;
margin: 8px 0;
display: inline-block;
border: 1px solid #ccc;
border-radius: 4px;
box-sizing: border-box;
}
button {
background-color: #4CAF50;
color: white;
padding: 14px 20px;
margin: 8px 0;
border: none;
border-radius: 4px;
cursor: pointer;
width: 100%;
}
button:hover {
background-color: #45a049;
}
.error-msg {
color: rgb(195, 0, 0);
font-size: 14px;
margin-bottom: 10px;
text-align: center;
}
</style>
</head>
<body>
<div id="resetBox">
<h1 style="text-align: center;">重置密码</h1>
<form>
<label for="username">用户名</label>
<input type="text" id="username" name="username" placeholder="请输入用户名" required>
<label for="newPassword">新密码</label>
<input type="password" id="newPassword" name="newPassword" placeholder="请输入新密码" required>
<label for="confirmPassword">确认密码</label>
<input type="password" id="confirmPassword" name="confirmPassword" placeholder="请确认密码" required>
<div class="error-msg" id="errorMsg"></div>
<button type="button" onclick="resetPassword()">重置密码</button>
</form>
</div>
<script>
function resetPassword() {
const username = document.getElementById('username').value.trim();
const newPassword = document.getElementById('newPassword').value.trim();
const confirmPassword = document.getElementById('confirmPassword').value.trim();
const errorMsg = document.getElementById('errorMsg');
if (newPassword !== confirmPassword) {
errorMsg.innerText = '新密码与确认密码不同';
} else {
// 模拟重置密码操作
if (username === '李四'||username === '安'||username === '西二') {
// 重置密码成功
alert('密码重置成功');
window.location.href = 'index.html'; // 返回登录页面
} else {
// 用户名不存在
errorMsg.innerText = '用户名不存在';
}
}
}
</script>
</body>
</html>
添加JDBC驱动
项目的pom.xml文件中添加JDBC驱动依赖;
<dependencies>
<!-- 添加MySQL JDBC驱动依赖 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.26</version>
</dependency>
</dependencies>
创建users数据库的数据表
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(100) NOT NULL,
PASSWORD VARCHAR(100) NOT NULL
);
连接登录界面的数据库
package com.qf.domian;
import java.sql.*;
public class TestConnectionMysql {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//jdbc连接MySQL数据库加载注册驱动
Class.forName("com.mysql.jdbc.Driver");
//连接数据库
String url="jdbc:mysql://127.0.0.1:3306/users?characterEncoding=UTF-8";
String uname="root";
String upass="123456";
Connection con=DriverManager.getConnection(url,uname,upass);
//创建执行对象
Statement sta = con.createStatement();
//增删改
String sql="INSERT INTO users(id,usename ,password)VALUES(1,'李四','123')";
int re=sta.executeUpdate(sql);
System.out.println(re);
2、创建数据库和表
在sqlyog数据库中创建数据库,并创建表,来存储计算器的历史记录
CREATE DATABASE calculator_history;
USE calculator_history;
CREATE TABLE history (
ID INT PRIMARY KEY,
operation1 VARCHAR(255),
operation2 VARCHAR(255),
operation_code VARCHAR(255),
result VARCHAR(255)
);
3、连接数据库
创建一个DatabaseConnector的Java类,用于连接数据库
import java.sql.*;
public class DatabaseConnector {
private static final String DB_URL = "jdbc:mysql://localhost:3306/arithmetic_calculator";
private static final String DB_USER = "root";
private static final String DB_PASSWORD = "123456";
public Connection connect() throws SQLException {
Connection connection = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
return connection;
}
}
创建的HistoryRepository类来操作数据库
package com.wd.domian;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
public class HistoryRecord {
private static final String DB_URL = "jdbc:mysql://127.0.0.1:3306/history?characterEncoding=UTF-8";
private static final String DB_USER = "root";
private static final String DB_PASSWORD = "123456";
public HistoryRecord(List<String> historyRecords) {
}
public static void saveHistory(int id,String operation, double result) {
try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD)) {
String sql = "INSERT INTO history (id,operation, result) VALUES (?, ?, ?)";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setInt(1,id);
pstmt.setString(2, operation);
pstmt.setDouble(3, result);
pstmt.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}
}
public static List<String> getAllHistory() {
List<String> historyList = new ArrayList<>();
try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD)) {
String sql = "SELECT * FROM history";
PreparedStatement pstmt = conn.prepareStatement(sql);
ResultSet rs = pstmt.executeQuery();
while (rs.next()) {
historyList.add(rs.getString("operation"));
}
} catch (Exception e) {
e.printStackTrace();
}
return historyList;
}
}
创建计算器界面并实现计算器的基本功能:
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.PreparedStatement;
import java.sql.SQLException;
public class Calculator extends JFrame {
private JTextField displayField;
private double firstNumber;
private String operator;
private ArrayList<String> history;
public Calculator() {
setTitle("Calculator");
setSize(400, 500);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
displayField = new JTextField(10);
displayField.setFont(new Font("Arial", Font.PLAIN, 20));
displayField.setEditable(false);
// 创建数字按钮
JButton[] numberButtons = new JButton[10];
for (int i = 0; i < 10; i++) {
numberButtons[i] = new JButton(Integer.toString(i));
}
// 创建运算符按钮
JButton addButton = new JButton("+");
JButton subtractButton = new JButton("-");
JButton multiplyButton = new JButton("*");
JButton divideButton = new JButton("/");
JButton sqrtButton = new JButton("√");
JButton equalsButton = new JButton("=");
JButton clearButton = new JButton("C");
JButton dotButton = new JButton(".");
// 创建历史记录按钮
JButton historyButton = new JButton("History");
// 创建按钮面板
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new GridLayout(5, 4));
buttonPanel.add(numberButtons[1]);
buttonPanel.add(numberButtons[2]);
buttonPanel.add(numberButtons[3]);
buttonPanel.add(addButton);
buttonPanel.add(numberButtons[4]);
buttonPanel.add(numberButtons[5]);
buttonPanel.add(numberButtons[6]);
buttonPanel.add(subtractButton);
buttonPanel.add(numberButtons[7]);
buttonPanel.add(numberButtons[8]);
buttonPanel.add(numberButtons[9]);
buttonPanel.add(multiplyButton);
buttonPanel.add(numberButtons[0]);
buttonPanel.add(sqrtButton);
buttonPanel.add(clearButton);
buttonPanel.add(divideButton);
buttonPanel.add(dotButton);
buttonPanel.add(equalsButton);
buttonPanel.add(historyButton);
// 添加事件监听器
for (int i = 0; i < 10; i++) {
numberButtons[i].addActionListener(new NumberButtonListener());
}
addButton.addActionListener(new OperatorButtonListener());
subtractButton.addActionListener(new OperatorButtonListener());
multiplyButton.addActionListener(new OperatorButtonListener());
divideButton.addActionListener(new OperatorButtonListener());
sqrtButton.addActionListener(new UnaryOperatorButtonListener());
equalsButton.addActionListener(new EqualsButtonListener());
clearButton.addActionListener(new ClearButtonListener());
dotButton.addActionListener(new DotButtonListener());
historyButton.addActionListener(new HistoryButtonListener());
// 初始化历史记录
history = new ArrayList<>();
public void loadHistoryFromDatabase() {
Connection connection = null;
try {
connection = DatabaseConnection.getConnection();
String query = "SELECT * FROM history";
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(query);
while (resultSet.next()) {
String expression = resultSet.getString("expression");
double result = resultSet.getDouble("result");
long timestamp = resultSet.getLong("timestamp");
JPanel panel = new JPanel();
panel.add(new JLabel(expression));
panel.add(new JLabel("Result: " + result));
JOptionPane.addPanel(timestamp, panel);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
// 将组件添加到窗口中
setLayout(new BorderLayout());
add(displayField, BorderLayout.NORTH);
add(buttonPanel, BorderLayout.CENTER);
setVisible(true);
}
private void calculate() {
String expression = displayField.getText();
String[] tokens = expression.split(" ");
double secondNumber = Double.parseDouble(tokens[tokens.length - 1]);
double result = 0;
switch (operator) {
case "+":
result = firstNumber + secondNumber;
break;
case "-":
result = firstNumber - secondNumber;
break;
case "*":
result = firstNumber * secondNumber;
break;
case "/":
result = firstNumber / secondNumber;
break;
}
displayField.setText(Double.toString(result));
history.add(expression + " = " + result);
// 重置第一个操作数和运算符
firstNumber = result;
operator = null;
}
private void clear() {
displayField.setText("");
firstNumber = 0;
operator = null;
}
private class NumberButtonListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
JButton button = (JButton) e.getSource();
String buttonText = button.getText();
displayField.setText(displayField.getText() + buttonText);
}
}
private class OperatorButtonListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
JButton button = (JButton) e.getSource();
String buttonText = button.getText();
String expression = displayField.getText();
if (!expression.isEmpty()) {
String[] tokens = expression.split(" ");
if (tokens.length == 3) {
calculate();
}
firstNumber = Double.parseDouble(displayField.getText());
operator = buttonText;
displayField.setText(expression + " " + buttonText + " ");
}
}
}
private class UnaryOperatorButtonListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
JButton button = (JButton) e.getSource();
String buttonText = button.getText();
if (!displayField.getText().isEmpty()) {
double number = Double.parseDouble(displayField.getText());
double result = 0;
if (buttonText.equals("√")) {
result = Math.sqrt(number);
}
displayField.setText(Double.toString(result));
history.add(buttonText + "(" + number + ") = " + result);
}
}
}
private class EqualsButtonListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
if (!displayField.getText().isEmpty()) {
calculate();
}
}
}
private class ClearButtonListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
clear();
}
}
private class DotButtonListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
if (!displayField.getText().contains(".")) {
displayField.setText(displayField.getText() + ".");
}
}
}
private class HistoryButtonListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
StringBuilder historyText = new StringBuilder("History:\n");
for (String entry : history) {
historyText.append(entry).append("\n");
}
JOptionPane.showMessageDialog(null, historyText.toString(), "History", JOptionPane.INFORMATION_MESSAGE);
}
public static void main(String[] args)
{
Calculator calculator=new Calculator();
}
}