第二次作业
一、实验目的
1.掌握软件开发的基本流程
2.掌握常用的软件开发方式和工具。
二、实验内容
设计一个包含登录界面的计算器软件,该软件可以实现第一次作业中的全部功能,同时可以保存用户的历史计算记录(保存数据最好使用数据库)。
三、实验环境
1、window11操作系统
2、idea
3、Visio
四、所涉及的流程图
1、注册流程图
2、登录流程图
3、计算器流程图
五、关键代码及UI展示
1、注册代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>register</title>
<style>
html{
height: 100%;
width: 100%;
overflow: hidden;
margin: 0;
padding: 0;
background: url(images/background.jpg) no-repeat 0px 0px;
background-repeat: no-repeat;
background-size: 100% 100%;
-moz-background-size: 100% 100%;
}
body{
display: flex;
align-items: center;
justify-content: center;
height: 100%;
}
input{
text-align: center;
border:none;
background-color: rgba(239, 248, 250, 0.1);
border-bottom:1px solid rgb(80, 196, 241);
width: 260px;
}
p{
text-align: center;
color: rgb(116, 114, 114);
}
.R_register{
margin-top: 30px;
width: 600px;
justify-content: center;
align-items: center;
text-align: center;
height: 600px;
background-color: rgba(246, 250, 250, 0.7);
box-shadow: 7px 7px 17px rgba(246, 250, 250, 0.4);
}
.R_login{
margin-top: 30px;
width: 300px;
justify-content: center;
align-items: center;
height: 600px;
background-color: rgba(167, 150, 150,0.6);
box-shadow: 7px 7px 17px rgba(52, 56, 66, 0.3);
}
#R_registerbtn {
border-color: cornsilk;
background-color: rgba(59, 194, 248, 0.6);
color: aliceblue;
border-style: hidden;
border-radius: 15px;
width: 190px;
height: 31px;
font-size: 16px;
}
#R_loginbtn{
border: 20px solid white;
background-color: rgba(71, 196, 245, 0.6);
border-radius: 50%;
color: aliceblue;
border-style: hidden;
border-radius: 15px;
width: 100px;
height: 31px;
font-size: 16px;
}
.title{
color: white;
text-align: center;
}
</style>
</head>
<div class="R_register">
<h3 style="color: rgb(122, 211, 247);">立即注册</h3>
<p>邮箱</p >
<p><input type="text" id="R_email"></p >
<p >用户名</p >
<p><input type="text" placeholder="用户名长度不能超过5位" id="R_user"></p >
<p> 性别</p >
<p>
<span>男</span>
<span><input style="width: auto;" type="radio" name="sex" value="男" checked="checked" ></span>
<span>女</span>
<span><input style="width: auto;" type="radio" name="sex" value="女" ></span>
</p >
<p >头像</p >
<p><input type="file" id="toux"></p >
<p >密码</p >
<p><input type="password" placeholder="密码长度至少为6位且为数字和字母的组合" id="R_pwd"></p >
<p >确认密码</p >
<p><input type="password" placeholder="两次密码需一致" id="R_repwd" onkeyup="checkpassword()"></p >
<span id="tishi"></span></input>
<p><button id="R_registerbtn" onclick=javascrtpt:jump()>注册</button></p >
</div>
<div class="R_login">
<br><br>
<h3 class="title">已有账号?</h3>
<p style="color: white;">已有账号就登录吧,好久不见!</p >
<br><br><br><br><br><br><br><br><br><br><br><br><br>
<p><button id="R_loginbtn" onclick=javascrtpt:jump3()>登录</button></p >
</div>
<script>
R_email.onchange = function(){
var R_email = this.value;
var reg = /^([a-zA-Z]|[0-9])(\w|\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/;
if(!reg.test(R_email)){
alert("邮箱格式不正确,请重新输入!");
return false;
}
}
R_user.onchange = function(){
var R_user= this.value;
var reg = /^\S{1,5}$/;
if(!reg.test( R_user)){
alert("用户名长度不能超过5位!");
return false;
}
}
R_pwd.onchange = function(){
var R_pwd = this.value;
var reg = /^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,}$/;
if(!reg.test(R_pwd)){
alert("密码长度要大于6位,由数字和字母组成,请重新输入!");
return false;
}
}
function checkpassword() {
var password = document.getElementById("R_pwd").value;
var repassword = document.getElementById("R_repwd").value;
if (password == repassword) {
document.getElementById("tishi").innerHTML = "<font color='green'>两次密码输入一致</font>";
} else {
document.getElementById("tishi").innerHTML = "<font color='red'>两次输入密码不一致!</font>";
}
}
function jump(){
localStorage.setItem("username",document.getElementById("R_user").value);
localStorage.setItem("password",document.getElementById("R_pwd").value);
localStorage.setItem("email",document.getElementById("R_email").value);
var Email = document.getElementById("R_email");
var User = document.getElementById("R_user");
var Toux = document.getElementById("toux");
var Password = document.getElementById("R_pwd");
var Repassword = document.getElementById("R_repwd");
if(Email.value == "" || User.value ==""|| Toux.value ==""|| Password.value =="") {
alert("邮箱、用户名、头像或密码不能为空!");
return false;
}
else if(Password.value == Repassword.value) {
alert("注册成功,欢迎进入登录界面!");
window.location.href="login.html";
}
else{
alert("注册信息有误!");
}
}
function jump3(){
window.location.href="login.html";
}
</script>
</body>
</html>
2、登录代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>login</title>
<style>
* {
margin: 0;
padding: 0;
}
html {
height: 100%;
width: 100%;
overflow: hidden;
margin: 0;
padding: 0;
background: url(images/background.jpg) no-repeat 0px 0px;
background-repeat: no-repeat;
background-size: 100% 100%;
-moz-background-size: 100% 100%;
}
body {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
}
#loginDiv {
width: 20%;
display: flex;
justify-content: center;
align-items: center;
height: 300px;
background-color: rgba(246, 250, 250, 0.6);
box-shadow: 7px 7px 17px rgba(246, 250, 250, 0.4);
border-radius: 300px;
}
#loginDiv:hover{
filter: grayscale(60%);
}
input{
text-align: center;
border:none;
background-color: rgba(239, 248, 250, 0.1);
border-bottom:1px solid rgb(80, 196, 241);
width: 200px;
}
#L_login {
border-color: cornsilk;
background-color: rgba(59, 194, 248, 0.8);
color: aliceblue;
border-style: hidden;
border-radius: 5px;
width: 100px;
height: 31px;
font-size: 16px;
}
#L_register {
border-color: cornsilk;
background-color: rgba(59, 194, 248, 0.8);
color: aliceblue;
border-style: hidden;
border-radius: 5px;
width: 100px;
height: 31px;
font-size: 16px;
}
</style>
</head>
<body>
<div id="loginDiv">
<form action="" id="form">
<table>
<h2 style="text-align: center; color: rgb(59, 194, 248);">立即登录</h2></br>
<tr><td style="text-align: center; color: gray;">用户邮箱</td></tr>
<tr><td><input class="line" type="text" id="L_email"></td></tr>
<tr><td style="text-align: center; color: gray;">密码</td></tr>
<tr><td > <input class="line" type="password" placeholder="密码长度至少为6位" id="L_pwd"></td></tr>
</table>
</br>
<p style="text-align: center;color: rgb(59, 194, 248);">忘记密码?</p >
<div style="text-align: center;margin-top: 15px;">
<input type="button" id="L_login" value="登录" onclick=javascrtpt:jump1()>
<input type="button" id="L_register" value="注册" onclick=javascrtpt:jump2()>
</div>
</form>
</div>
<script>
L_email.onchange = function(){
var L_email = this.value;
var reg = /^([a-zA-Z]|[0-9])(\w|\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/;
if(!reg.test(L_email)){
alert("邮箱格式不正确,请重新输入!");
return false;
}
}
L_pwd.onchange = function(){
var L_pwd = this.value;
var reg = /^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,}$/;
if(!reg.test(L_pwd)){
alert("密码长度要大于6位,由数字和字母组成,请重新输入!");
return false;
}
}
var email=localStorage.getItem("email");
var password=localStorage.getItem("password");
console.log("email:"+email);
console.log("pwd:"+password);
function jump1(){
console.log(document.getElementById("L_email").value);
console.log(+document.getElementById("L_pwd").value);
var Email = document.getElementById("L_email");
var Password = document.getElementById("L_pwd");
if(email==document.getElementById("L_email").value && password==document.getElementById("L_pwd").value){
alert("登录成功,点击确定进入计算器界面!");
window.location.href="My_Album.html";
}
else if(Email.value == "" || Password.value =="") {
alert("邮箱或密码不能为空!");
return false;
}
else{
alert("邮箱或密码错误!");
return false;
}
}
function jump2(){
window.location.href="register.html";
}
</script>
</body>
</html>
3、连接数据库代码
package LJ;
import java.sql.*;
public class Main {
public static void main(String[] args) {
// 1. 导入数据库驱动程序的jar包
System.out.println("加载驱动程序");
Class.forName("com.mysql.jdbc.Driver");
// 2. 加载并注册驱动程序
System.out.println("注册驱动程序");
Connection conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/mydatabase", "root", "password");
// 3. 创建数据库连接
System.out.println("创建数据库连接");
Statement stmt = conn.createStatement();
// 4. 创建Statement或PreparedStatement对象
System.out.println("执行SQL语句");
ResultSet rs = stmt.executeQuery("SELECT * FROM mytable");
// 5. 执行SQL语句
while (rs.next()) {
System.out.println(rs.getString("name")); // 获取查询结果
}
// 6. 获取查询结果
rs.close(); // 关闭ResultSet对象
stmt.close(); // 关闭Statement对象
conn.close(); // 关闭连接
}
}
4、计算器代码
package JSQ;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Stack;
//处理计算结果异常
class MyException extends Exception{
private static final long serialVersionUID = 1649159247013670200L;
public MyException() {
super();
}
public MyException(String message) {
super(message);
}
}
public class SwingConsole {
public static void run(final JFrame f,final int width,final int height){
//调用invokeLater来请求事件分发线程以运行某段代 码
//必须将这段代码放入一个Runnable对象的run方法中,并将该指定Runnable对象作为参数传递给invokeLater。
SwingUtilities.invokeLater(new Runnable(){
//invokeLater函数会立即返回,不会等到事件分发线程执行完这段代码。
public void run(){
f.setTitle(f.getClass().getSimpleName());
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(width,height);
f.setVisible(true);
}
});
}
}
class calculator2 extends JFrame{
private static final long serialVersionUID = 1L;
//定义变量
private JTextField textField; //输入文本框
private String input; //结果
private JButton button; //按钮
private JLabel jlabel;
//在构造方法中重写,创建框架,创建组件,添加组件,以及给组件注册事件监听器
public calculator2() {
//由于在线程设置里设置了title,所以这里不用再设计
super("计算器");
//在屏幕上显示计算器的位置为(400, 300)
this.setLocation(400, 300);
input = "";
//得到框架的内容窗格,才可以添加组件,使用默认的BorderLayout
Container container = this.getContentPane();
//创建中间容器JPanel
JPanel panel = new JPanel();
//设置颜色
this.setBackground(Color.white);
//创建文本框,指定单行长度
textField = new JTextField(30);
textField.setEditable(false); //文本框禁止编辑
textField.setHorizontalAlignment(JTextField.LEFT);
//textField.setBounds(100, 100, 20, 20); //在容器布局为空情况下生效
textField.setPreferredSize(new Dimension(200,30));
//设置文本框颜色
textField.setBackground(Color.YELLOW);
//使用add来添加组件,添加文本框到北部
container.add(textField, BorderLayout.NORTH);
//添加标题
jlabel = new JLabel("DESIGN BY **",JLabel.CENTER);
container.add(jlabel,BorderLayout.SOUTH);
String[] name=
{"1","2","3","+","4","5","6","-","7","8","9","*","0","C","=","/"};
//给中间容器设置布局管理器,GridLayout(4,4,1,1)设置行数,列数,组件水平距离,垂直距离
panel.setLayout(new GridLayout(4,4,1,1));
//将16个按钮放入JPanel
for(int i=0;i<name.length;i++) {
button = new JButton(name[i]);
//给按钮添加事件监听器
button.addActionListener(new MyActionListener());
//添加按钮组件
panel.add(button);
if((i==3)||(i==7)||(i==11)||(i==14)||(i==15))button.setBackground(Color.PINK);
if(i==14)button.setBackground(Color.ORANGE);
}
//添加JPanel到中部
container.add(panel,BorderLayout.CENTER);
String[] name2= {"%","1/X","sqrt"};
JPanel panel2 = new JPanel();
panel2.setLayout(new GridLayout(3,1,1,1));
//将16个按钮放入JPanel
for(int i=0;i<name2.length;i++) {
button = new JButton(name2[i]);
//给按钮添加事件监听器
button.addActionListener(new MyActionListener());
//添加按钮组件
button.setBackground(Color.GREEN); panel2.add(button); }
//添加JPanel到中部
container.add(panel2,BorderLayout.EAST);
}
//继承事件适配器,重写事件监听器的方法
//内部类实现按钮响应,将输入值送入
class MyActionListener implements ActionListener{
public void actionPerformed(ActionEvent e) {
int cnt=0;
String actionCommand = e.getActionCommand();
//获取按钮上的字符串
//用equals函数来判断是否为符号,若是括号中的则为true
if(actionCommand.equals("+") || actionCommand.equals("-") ||
actionCommand.equals("*")
|| actionCommand.equals("/")||actionCommand.equals("%"))
{
input += " " + actionCommand + " ";
}
//按下C清除输入
else if(actionCommand.equals("C")) {
input = "";
}
//按下1/x求相反数
else if(actionCommand.equals("1/X")) {
input += " " + actionCommand + " ";
}
//按下sqrt求相反数
else if(actionCommand.equals("sqrt")) { input += " " + actionCommand + " "; }
//按下等号,若有异常,则调用MyException
else if(actionCommand.equals("=")) {
try {
input+= "="+calculate(input);
} catch (MyException e1) {
if(e1.getMessage().equals("Infinity"))
input+= "=" + e1.getMessage();
else
input = e1.getMessage();
}
//文本框输出input
textField.setText(input);
//储存结果清零
input="";
//cnt置1表示计算结束
cnt = 1;
}
else//按下数字
input += actionCommand;
//cnt为零时,输入继续,储存之前的结果
if(cnt == 0)
textField.setText(input);
}
}
//借助栈来完成表达式的计算
private String calculate(String input) throws MyException{
//创建数组
String[] comput = input.split(" ");
//创建栈
Stack<Double> stack = new Stack<>();
//创建变量
Double m = Double.parseDouble(comput[0]);
//第一个操作数入栈
stack.push(m);
//将字符串分割成字符串数组,依次运算
for(int i = 1; i < comput.length; i++) {
//数组奇数位为运算符(从第0位开始),偶数位为操作数,因此可将偶数为操作数进栈,
if(i%2==1) {
//遇见+(-)运算符,则将下一个数以正(负)的形式压人栈中
if(comput[i].equals("+"))
stack.push(Double.parseDouble(comput[i+1]));
if(comput[i].equals("-"))
stack.push(-Double.parseDouble(comput[i+1]));
//遇见*或/运算符,则将栈顶元素出栈与数组后一元素进行计算,并将其结果重新压入栈中,直至遍历至数组最后一个元素。最后将栈中的元素进行求和。
if(comput[i].equals("*")) {
Double d = stack.peek(); //取栈顶元素
stack.pop(); //将栈顶元素出栈
stack.push(d*Double.parseDouble(comput[i+1]));//做乘法再入栈
}
if(comput[i].equals("/")) {
//将前一个数出栈做乘法再入栈
double help = Double.parseDouble(comput[i+1]);
if(help == 0)
throw new MyException("Infinity"); //若0是除数,不会继续执行该函数
double d = stack.peek();
stack.pop();
stack.push(d/help);
}
if(comput[i].equals("%")) {
double help = Double.parseDouble(comput[i+1]);
if(help == 0)
throw new MyException("Infinity"); //若0是除数,不会继续执行该函数
double d = stack.peek(); //取栈顶元素
stack.pop(); //将栈顶元素出栈
stack.push(d%Double.parseDouble(comput[i+1]));//做求余再入栈
}
if(comput[i].equals("sqrt")) {
Double d = stack.peek(); //取栈顶元素
stack.pop(); //将栈顶元素出栈
stack.push(Math.sqrt(d));//做乘法再入栈
}
if(comput[i].equals("1/X")) {
double help = Double.parseDouble(comput[i-1]);
if(help == 0)
throw new MyException("Infinity"); //若0是除数,不会继续执行该函数
else{
double d = stack.peek(); //取栈顶元素
stack.pop(); //将栈顶元素出栈
stack.push(1/d);}//做求余再入栈
}
}
}
//将栈中元素求和
double d = 0;
while(!stack.isEmpty()) {
d += stack.peek();
stack.pop();
}
//强制转换类型为字符,返回结果
String result = String.valueOf(d);
return result;
}
//main方法
public static void main(String[] args) {
//创建计算机,并且设置长宽
SwingConsole.run(new calculator2(), 500, 500);
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现