第二次作业
一、实验目的
1.掌握软件开发的基本流程
2.掌握常用的软件开发方式和工具。
二、实验内容
1.设计一个包含登录界面的计算器软件,该软件可以实现第一次作业中的功能,同时可以保存用户的历史计算记录(保存数据最好使用数据库)。
三、登录流程图
四、登录效果展示
1.登录成功
2.用户名错误
3.密码错误
五、计算器实现展示页面
1.测试“加”法
2.测试“乘法”
五、具体代码
1.jdbc连接数据库
package jisuanqi;
//public class TestConnectionMysql {
//
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class TestConnectionMysql {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//jdbc连接mysql数据库
//加载注册驱动
Class.forName("com.mysql.jdbc.Driver");
//本机ip有几种表示形式
/**
* 1:localhost
* 2:127.0.0.1
* 3:计算机名
* 4:ip cmd ipconfig
*
*
*
*/
//连接数据库
String url="jdbc:mysql://127.0.0.1:3306/history?characterEncoding=UTF-8";
String uname="root";
String upass="123456";
Connection con = DriverManager.getConnection(url, uname, upass);
//创建执行对象
Statement sta = con.createStatement();
//增删改executeUpdate
String sql="INSERT INTO stu VALUES(1,'翠花','男',18)";
int re = sta.executeUpdate(sql);
System.out.println(re);
}
}
2.登录代码
package jisuanqi;
//public class login {
//}
import javax.swing.*;
import java.awt.*;
public class login{
public static void main(String[] args) {
//创建一个主要框架,将其命名为”登录"
JFrame jFrame = new JFrame("登录");
jFrame.setSize(900,507);
jFrame.setLayout(null);
//添加标签【计算器计算系统】
JLabel textComputerManage = new JLabel("用户登录界面");
textComputerManage.setForeground(new Color(0xFF000000));
textComputerManage.setFont(new Font("黑体", Font.PLAIN,50));
textComputerManage.setBounds(280,50,800,100);
jFrame.add(textComputerManage);
//0xFF000000 0x0010FF
//添加标签【用户名】
JLabel textUser = new JLabel("用户名:");
textUser.setForeground(new Color(0xFF000000));
textUser.setFont(new Font("黑体", Font.PLAIN,30));
textUser.setBounds(200,140,200,100);
jFrame.add(textUser);
//添加输入框【用户名输入框】
JTextField user = new JTextField(20);
user.setFont(new Font("黑体", Font.PLAIN,18));
user.setSelectedTextColor(new Color(0xFF000000));
user.setBounds(330,170,280,40);
jFrame.add(user);
//添加标签【密码】
JLabel textPassword = new JLabel("密码 :");
textPassword.setForeground(new Color(0xFF000000));
textPassword.setFont(new Font("黑体", Font.PLAIN,30));
textPassword.setBounds(200,200,200,100);
jFrame.add(textPassword);
//添加密码输入框【密码】
JPasswordField password = new JPasswordField(20);
password.setBounds(330,230,280,40);
jFrame.add(password);
//添加按钮【登录】
JButton jButton = new JButton("登录");
jButton.setForeground(new Color(0xFF000000));
jButton.setBackground(new Color(0x38FF00));
jButton.setFont(new Font("黑体", Font.PLAIN,20));
jButton.setBorderPainted(false);
jButton.setBounds(300,330,100,50);
jFrame.add(jButton);
//添加按钮【注册】
JButton register = new JButton("注册");
register.setForeground(new Color(0xFF000000));
register.setBackground(new Color(0xECA871));//0xECA871
register.setFont(new Font("黑体", Font.PLAIN,20));
register.setBorderPainted(false);
register.setBounds(500,330,100,50);
jFrame.add(register);
//对按钮事件进行处理
jButton.addActionListener((e -> {
String pwd = new String(password.getPassword());
if(user.getText().equals("sleep")){
if(pwd.equals("123456")){
//密码账号正确,进入计算器计算系统
//进入计算器计算系统
jFrame.setVisible(false);//将登录界面设定为不可见
//new StudentManage().StudentMainInterface();
}else{
//密码不正确
JOptionPane.showMessageDialog(jFrame,"密码错误","提示",JOptionPane.INFORMATION_MESSAGE);
//将密码框置空
password.setText("");
}
}else{
//用户名错误
JOptionPane.showMessageDialog(jFrame,"用户名错误","提示",JOptionPane.INFORMATION_MESSAGE);
//将用户名和密码置空
user.setText("");
password.setText("");
}
}));
jFrame.setLocationRelativeTo(null);
jFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
jFrame.setResizable(false);
jFrame.setVisible(true);
}
}
3.计算器实现代码
package jisuanqi;
//public class carculator {
//}
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
//计算器
public class carculator extends JFrame {
private JTextField display;//定义输入框
public static void main(String[] args) {
/*没有写UI界面前的测试
Scanner sc=new Scanner(System.in);
System.out.println("输入要计算的表达式:");
String num=sc.nextLine();
//封装之后之前public型转为private,不能在这里直接调用
// //测试输出,看拆分的表达式是否正确
// List<String> list=carculatorUtils.split(num);
// System.out.println(list);
//
// System.out.println("==========");
// list=carculatorUtils.toPostfix(num);
// System.out.println(list);
//
// System.out.println("==========");
// System.out.println(carculatorUtils.getResultByPostFix(list));
//直接调用封装后的方法
System.out.println(carculatorUtils.start(num));
*/
new carculator();
}
public carculator() {
//一、创建窗口
//设置窗口名字
this.setTitle("郭伟伟的计算器");
//设置窗口大小
this.setSize(400, 500);
//设置窗口不可改变大小
this.setResizable(false);
//二、为窗口添加输入框
//创建输入框
display=new JTextField();
//设置输入框宽高
display.setPreferredSize(new Dimension(400,50));
//设置输入框字体类型,样式,大小
display.setFont(new Font("Arail",Font.PLAIN,20));
//设置文本对齐方式,右对齐
display.setHorizontalAlignment(SwingConstants.RIGHT);
//设置边距
display.setMargin(new Insets(10,10,10,10));
//将输入框添加到窗口
this.add(display,BorderLayout.NORTH);
//三、添加按钮
//创建控制面板
JPanel panel=new JPanel();
//分割区域
panel.setLayout(new GridLayout(5,4));
//添加按钮
for(int i=0;i<10;i++) {
JButton btn=creatButton(i+"");//添加数字按钮
btn.setFont(new Font("Arail",Font.PLAIN,20));//设置字体,样式,大小
panel.add(btn);//把按钮添加到面板中
}
JButton add=creatButton("+");
JButton substract=creatButton("-");
JButton multiply=creatButton("*");
JButton divide=creatButton("/");
JButton point=creatButton(".",true);//小数点
JButton eq=creatButton("=",false);
JButton clear=creatButton("c",false);//清除,整体删除
JButton del=creatButton("x",false);//删除,一个字符一个字符删
//批量添加按钮到面板
addToComponent(panel,add,substract,multiply,divide,point,eq,clear,del);
//给”清除”添加事件
clear.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
display.setText("");
}
});
//给“删除”添加事件
del.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
String msg=display.getText();//获取文本
if(msg.length()>0) {//有输入时才删除
display.setText(msg.substring(0,msg.length()-1));
}
}
});
//给“等于”添加事件
eq.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
if(display.getText().length()>0) {
String result=carculatorUtils.start(display.getText());
display.setText(result);
}
}
});
//把面板添加到窗口中
this.add(panel, BorderLayout.CENTER);
//设置窗口可视化
this.setVisible(true);
//设置窗口关闭
this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
//DISPOSE_ON_CLOSE:点击右上角的“X”只关闭当前窗口,
//EXIT_ON_CLOSE:结束窗口所在的应用程序。在窗口被关闭的时候会退出JVM,软件所有窗口都会关闭
}
//创建按钮,添加事件
private JButton creatButton(String text) {
return creatButton(text,true);
}
//该方法用于,创建按钮
//flag=true添加事件,否则不添加
private JButton creatButton(String text,boolean flag) {
JButton btn=new JButton(text);//创建按钮,并指定文本内容
btn.setFont(new Font("Arail",Font.PLAIN,20));
//增加一个事件,让文本显示在输入框(所以输入框的定义也要放在之前)
if(flag) {
btn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
String msg=display.getText();//获取文本
display.setText(msg+text);//拼接,点一个数字输入一个数字
}
});
}
return btn;
}
//该方法用于,批量把按钮添加到面板,把js添加到com中
private void addToComponent(JComponent com,JComponent...js) {
for(JComponent j:js) {
com.add(j);
}
}
}
package jisuanqi;
//public class carculatorUtils {
//}
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
//计算器工具类:
public class carculatorUtils {
//第四步:---封装:输入一个表达式,调用该方法,直接计算出结果
public static String start(String num) {
return getResultByPostFix(toPostfix(num));
}
//第三步:---通过后缀表达式获得最终结果
private static String getResultByPostFix(List<String> exp) {
//遍历集合中的元素
for(int i=0;i<exp.size();i++) {
String val=exp.get(i);//获取当前的元素
if(!isOperator(val)) {//如果当前元素是操作数,则继续遍历
continue;
}
//如果是运算符,则把该操作符前两位数进行计算
double result=0;
double prevOne=Double.parseDouble(exp.get(i-1));//获取操作符前一个数
double prevTwo=Double.parseDouble(exp.get(i-2));//前二的数
//判断运算符类型
switch(val) {
case "+":
result=prevOne+prevTwo;
break;
case "-":
result=prevTwo-prevOne;
break;
case "*":
result=prevOne*prevTwo;
break;
case "/":
result=prevTwo/prevOne;
break;
}
/* 计算完后,这三个字符串就要退出,不再参与
* 原来的操作符位置i被新的结果result替换,+""是因为都是字符串
* 原来的操作数退出
* 下标i变为i-2;
*/
exp.set(i, result+"");//替换
exp.remove(i-1);//移除
exp.remove(i-2);//移除
i=i-2;
}
return exp.get(0);
}
//第二步:---将中缀表达式转化为后缀表达式 有问题
private static List<String> toPostfix(String num){
List<String> list=split(num);//获取表达式的各个元素
List<String> exp=new ArrayList<>(list.size()); //用于保存后缀表达式
//运算符暂存在栈中,数值保存在数组中
Stack<String> optStack=new Stack<>();//暂存运算符
//遍历集合中分割后的表达式(操作符或运算符)
for(String e:list ) {
//一、如果是操作数
if(!isOperator(e)){
exp.add(e);//添加
continue;
}
//二、如果是操作符
//1.如果栈为空,操作符入栈
if(optStack.isEmpty()) {
optStack.push(e);
continue;
}
//2.如果栈不为空,查看栈顶元素
String top=optStack.peek(); //查看栈顶元素
//2.1如果遇到的操作符元素的优先级高于栈顶元素,待入栈操作符入栈
if(judgePriority(e,top)) {//遇到的>栈顶,true
optStack.push(e);//入栈
continue;
}
//2.2否则(遇到的操作符优先级<=栈顶操作符优先级),栈顶元素出栈,
// 直到栈顶元素优先级小于遇到的操作符,或者栈为空时停止出栈
while(!optStack.isEmpty() && !judgePriority(e,top)) {
exp.add(top);//操作符入数组,跟在操作数后面
optStack.pop();//栈顶出栈
if(optStack.size()>0) {
top=optStack.peek();
}
}
//将当前操作符入栈
optStack.push(e);
}
//栈不为空,剩余操作符全部出栈,追加到后面
while(!optStack.isEmpty()) {
exp.add(optStack.pop());
}
return exp;
}
/* 判断运算符优先级
* opt1优先级>opt2,则为true
* opt1优先级<=opt2,则为false
*/
private static boolean judgePriority(String opt1,String opt2) {
if( eq(opt1,"+","-")) {
return false;//opt1"+或-" <= opt2"*或/"
}
if(eq(opt2,"+","-")) {
return true;//opt1"*或/" > opt2"+或-"
}
return false;//opt1"*或/" = opt2"*或/"
}
//public用于判断strs是否存在一个元素和src相等,只要存在一个相等则返回true
public static boolean eq(String src,String...strs) {//rs是一个数组
for(String str:strs) {
if(src.equals(strs)) {
return true;
}
}
return false;
}
// 第一步:--将数学表达式拆分
private static List<String> split(String num) {// 返回值为数组list
List<String> list = new ArrayList<>();//List是一个集合
int len = num.length();
int start = 0;
int end = 0;
for (int i = 0; i < len; i++) {// i表示当前索引,指向一个个的字符
char tmp = num.charAt(i);// 获取当前字符
if (isOperator(tmp)) {// 如果tmp是运算符,就入栈
list.add(tmp + "");
continue;
}
// 如果是数字或者小数点
start = i;// start表示指向一个小数的开始,例:2.3的2
// if(i+1<len) {//判断是否还有下一个字符
// char next=num.charAt(i+1);//获取当前字符;
// //最后i+1可能会出现越界行为,
// //此时在外面再加一个判断语句,当i+1<len即不越界时
// //才判断next指向的是不是运算符
// while(i<len && !isOperator(next)) {
// i++;
// if(i+1>=len) break;//如果越界则退出循环,所有字符也都遍历结束
// next=num.charAt(i+1);
// }
// }
// 对上面部分做出优化
while (i + 1 < len && !isOperator(num.charAt(i + 1))) {
i++;
}
String str = num.substring(start, i + 1);// 字符串截取,得到小数5.2
list.add(str);// 把获得的小数添加到栈
}
return list;
}
// 判断str是否是运算符
private static boolean isOperator(char ch) {
String str=ch+"";//把字符型操作符转为字符串
return str.equals("+") || str.equals("-") || str.equals("*") || str.equals("/") || str.equals("(")
|| str.equals(")");
}
// 判断str是否是运算符
private static boolean isOperator(String str) {
return str.equals("+") || str.equals("-") || str.equals("*") || str.equals("/") || str.equals("(")
|| str.equals(")");
}
// 判断是不是数字
private boolean isDigit(char ch) {
return ch >= '0' && ch <= '9';
}
}
【推荐】国内首个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,普通电脑可用
· 按钮权限的设计及实现