面向对象程序综合设计课程设计
1. 项目简介
功能描述:一个学生信息管理系统,从文件中读取信息并且写入文件,功能上可以实现登录,验证,利用链表实现对学生信息的增删改查等功能,做了对人友好的GUI界面。有参考一些代码。
参考git地址或博客地址:
https://blog.csdn.net/zhrb/article/details/118353040
https://www.cnblogs.com/jiangxiulian/p/5961990.html
https://www.jianshu.com/p/be65848efbd3
https://blog.csdn.net/qq_45278500/article/details/122069784
https://www.cnblogs.com/yan-2003/p/17000877.html
个人负责任务:
- 添加学生功能:姓名、学号、性别、出生年月日。学号自动生成且唯一
- 添加学生成绩功能
- 根据学生学号查找学生成绩,并在界面上显示姓名、学号和成绩,学号不存在的给出提示信息
- 根据学生姓名(支持模糊匹配)查找学生成绩,并在界面上显示姓名、学号和成绩,如果有多个相同姓名学生存在,一起显示出来,姓名不存在的给出提示信息
- 生成学生学习情况报表:报表包含学号、姓名、各科目成绩及对应的该科目班级平均值,总成绩以及班级总成绩平均值。最后以总成绩降序在图形界面输出,并可将该排序结果按照输出至"成绩表.txt"文件
- 支持对学生信息的修改与删除(要在文件或数据库中有所体现),不能修改学号。
- 测试:支持随机生成10万个学生及其姓名、学号、成绩放入文本文件,以进行测试。(学号不能相同,每颗的成绩以80分为中心成正态分本)(重要加分项)
- 支持用户登录、验证操作
- 界面:GUI 或 Web
2. 功能架构图
3. 个人任务简述
-
登录与验证,实现图片验证码。
-
学生的增删改查,实现模糊匹配与表格展示。
-
学生随机生成,实现随机生成姓名与生成成绩以80为中心正态分布。
-
使用流实现文件的读写。
-
完成的任务与功能:
简单描述将自己完成的有特色的地方、重难点地方。
- 登录功能:使用字符串匹配,通过getText得到输入框的内容,然后与设定好的匹配,随机生成一个算式并且生成验证码图片作为验证,如果输入的账号密码以及验证码都正确,就登录成功。密码的输入使用了JPasswordField类,这样可以使输入加密,更加安全。
- 读写文件功能:使用流的方法,进行文件的读写。
- 随机生成功能:使用了Random和Math包中自带的正态分布函数,实现了以80为中心的正态分布的生成数,可以生成100000个数据,利用0xA0码实现姓名的随机(参考了代码)。
- 增删改功能:使用了链表,通过对链表的修改实现对文件的修改。
- 查功能:使用了链表,但是GUI页面学习使用了JTable构建一个表格形式的展示。
- Git提交记录截图:
单人作品,无需使用git。
4. 本人负责功能详解
分功能、模块详细描述自己完成的任务,也可描述自己花了很大精力、时间研究想用于课程设计但未完成的部分。重难点、特色部分请标星*,并往前放。
每个任务或模块按照以下结构描述:简述、关键代码截图。
- *面向对象设计
- main包里面放的是该系统内部需要完成的函数,例如创建,文件的读写等。system包里面放的是该系统面向用户的一些外部功能,比如添加成绩等。
- *验证码功能:
- 采用了随机生成以及画图的功能,可以实现生成的是一个算式图片,类似于现实中的验证码。
- 难点:画图技术。
- 解决方法:查询Java画图需要的函数,并且参考了同学的代码,然后查询每个函数的作用,实现自己的验证码的生成。
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if(this.code == null || this.code.length() != this.codeLength) {
this.code = generateCode();
}
width = this.codeLength * 16 + (this.codeLength - 1) * 10;
super.setSize(width, height);
super.setPreferredSize(new Dimension(width, height));
//字体Font
Font mFont = new Font("Arial", Font.BOLD | Font.ITALIC, 25);
g.setFont(mFont);
//绘制出验证码的背景的矩形轮廓
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(getRandColor(200, 250));
//fillRect() 方法绘制“已填色”的矩形 x 矩形左上角的 x 坐标 y 矩形左上角的 y 坐标 width 矩形的宽度,以像素计 height 矩形的高度,以像素计
g2d.fillRect(0, 0, width, height);
g2d.setColor(getRandColor(180, 200));
//绘制指定矩形的边框,矩形的左边和右边位于 x 和 x + width。顶边和底边位于 y 和 y + height。使用图形上下文的当前颜色绘制该矩形。
g2d.drawRect(0, 0, width - 1, height - 1);
//绘制出验证码背景的线
int i = 0, len = 100;
for (; i < len; i++) {
//该方法用于在画布上绘制直线,通过指定直线的两个端点坐标来绘制。该方法只能绘制单条直线
int x = random.nextInt(width - 1);
int y = random.nextInt(height - 1);
int x1 = random.nextInt(width - 10) + 10;
int y1 = random.nextInt(height - 4) + 4;
g2d.setColor(getRandColor(180, 200));
g2d.drawLine(x, y, x1, y1);
}
//绘制出验证码的具体字母
i = 0; len = this.codeLength;
//getFontMetrics返回值是FontMetrics对象,该对象已被初始化为描述这个字体对象的基本字体。
FontMetrics fm = g2d.getFontMetrics();
int base = (height - fm.getHeight())/2 + fm.getAscent();
for(;i<len;i++) {
//用来确定是顺时针还是逆时针
int b = random.nextBoolean() ? 1 : -1;
// rotate() 函数定义了一种将元素围绕一个定点旋转而不变形的转换
//角度+顺逆时针
g2d.rotate(random.nextInt(10)*0.01*b);
g2d.setColor(getRandColor(20, 130));
//drawString(String str,int x,int y):String str是可以在屏幕上显示的字符串。整数类型x和y是在图形窗口上保持x和y位置的变量。
g2d.drawString(code.charAt(i)+"", 16 * i + 10, base);
}
} ```
- *展示功能
- 对链表进行遍历,重新排序,得到新的链表,然后实现表格对该链表的输出。
- 难点:不知道应该怎么样输出,最开始是想直接新建页面然后文本输出,但是不知道长度也就无法得知要创建多少个文本框。
- 解决方法:使用一个vector数组,这个数组可以没有规定的长度,很适合。
for(int i=0;i<len;i++)
{
//不能用Student类,因为Student类中没有平均成绩,长度不对。
Vector rowData = new Vector();
rowData.add(Main.student.get(i).getNum());
rowData.add(Main.student.get(i).getName());
rowData.add(Main.student.get(i).getSex());
rowData.add(Main.student.get(i).getBirthday().substring(0, 4)+"-"+Main.student.get(i).getBirthday().substring(4, 6)+"-"+Main.student.get(i).getBirthday().substring(6, 8));
rowData.add(Main.student.get(i).getChinese());
rowData.add(String.format("%.2f", averCh));
rowData.add(Main.student.get(i).getEnglish());
rowData.add(String.format("%.2f", averEn));
rowData.add(Main.student.get(i).getPe());
rowData.add(String.format("%.2f", averPe));
rowData.add(String.format("%.2f",Main.student.get(i).getTotalsorces()));
rowData.add(String.format("%.2f", avertotalsorces));
data.add(rowData);
}
JScrollPane pane = new JScrollPane(table);
// 把表格放到滚动面板中(表头将自动添加到滚动面板顶部)
JScrollPane scrollPane = new JScrollPane(table);
// 添加滚动面板到内容面板
panel.add(scrollPane);
// JScrollPane pane = new JScrollPane(table);
// 设置内容面板到窗口
jf.setContentPane(panel);
jf.pack();
jf.setSize(1000, 600);
jf.add(scrollPane, BorderLayout.CENTER);
//数据居中显示
//DefaultTableCellRenderer用于自定义,比如字体颜色等
DefaultTableCellRenderer r = new DefaultTableCellRenderer();
//setHorizontalAlignment文本左右对齐的方法
r.setHorizontalAlignment(JLabel.CENTER);
table.setDefaultRenderer(Object.class, r);
- *添加成绩功能
- 每次都添加所有学生的一门学科的成绩。
- 难点:这里我想到只生成一个界面,但是会随着我的操作更新这个界面上的信息,这样会比较简单,但是,每次界面都不会停留,会直接跳转到最后一个学号,这样不行,我试了很多种方法,试过加一个鼠标监听器监听是否有按按钮,都不行。
- 解决方法:增加一个单独的GUI函数,创建新面板,用for循环暴力把这个页面循环输出,每个同学都生成一个页面,这样才写出来,但是这个界面会变得非常的繁杂,不是很简洁,还有改善的空间。
public Addscores(){
Object[] possibleValues = { "语文", "英语", "体育"};
//JOptionPane.showInputDialog方法返回用户输入的字符串。
//在输入对话框设置下拉菜单选择框
Object selectedValue = JOptionPane.showInputDialog(null, "请选择一门学科", "选择输入",JOptionPane.QUESTION_MESSAGE, null,possibleValues, possibleValues[0]);
//selectedValue:选中的dropdownlist中选项的值,为string, 只读不写
this.setSize(300,150);
this.setTitle("添加成绩");
this.setAlwaysOnTop(true);
//根据以下场景设置窗口相对于指定组件的位置。放到中间
this.setLocale(null);
this.setDefaultCloseOperation(WindowConstants.HIDE_ON_CLOSE);
//创建一个新的流布局管理器
this.setLayout(new BorderLayout());
for(int i=Main.student.size()-1;i>=0;i--)
{
new AddscoresGui(i,selectedValue);
}
}
- 用流读写文件
- 难点:最开始不知道要用哪种方式比较好,在把一行数据转为链表时不知道怎么转换。
- 解决方法:关于读写文件我参考了我的实验作业,找到了合适的方法,然后链表的话使用了正则表达式,将一行数据拆开,组装成Student对象。
//缓冲区读取内容,避免中文乱码
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(new FileInputStream(FileName),"UTF-8"));
//字符转换流InputStreamReader防止中文乱码
String line = null;
while((line=br.readLine())!=null)//不可以while(br!=null)
{
//正则表达式,用于判断换行等字符,如果遇到更多相同换行则会合并为一个,返回字符型数组
String[] stu=line.split("\s+");
int num=Integer.parseInt(stu[0]);
String name=stu[1];
String birthday=stu[2];
String sex=stu[3];
double Chinese=Double.parseDouble(stu[4]);
double English=Double.parseDouble(stu[5]);
double PE=Double.parseDouble(stu[6]);
double totalsorces=Chinese+English+PE;
//建立对象
Student Stu=new Student();
Stu.setNum(num);
Stu.setName(name);
Stu.setBirthday(birthday);
Stu.setSex(sex);
Stu.setChinese(Chinese);
Stu.setEnglish(English);
Stu.setPe(PE);
Stu.setTotalsorces(totalsorces);
Main.student.add(Stu);
}
- 增删改查功能
- 实现学生信息的增删改查,实现姓名的模糊查找。
- 难点:没什么难点,就是找到想要的GUI相关的函数花了一些时间。
- 解决方法:百度搜索相关作用,就可以找到对应的函数。
- 登录功能
- 没有难点,就是最普通的字符串匹配。
5. 课程设计感想
-
读文件的时候只能一行一行的读,无法按照要求读文件
先按行读取文件,然后通过正则表达式划分,存为字符数组,然后通过这个数组来建立链表,这样就可以接下来通过链表来进行下面的编程。 -
一个GUI界面无法跳转到另一个界面,另一个界面为空白
首先这个问题困扰了我一段时间,如果要从一个页面跳转为另外一个页面的话,会变成如下结果:
会有第二个页面,但是第二个页面无法显示,只有一个表头。
这个地方有两个解决方法:
- 老师的方法是第二个界面setvisible前,pack一下,但是这个方法还是无法显示,我不知道是为什么,按理来说,刷新了之后就应该显示出来了,所以,我使用了第二个方法。
- 分函数写。我最开始是打算全部放到Main函数中然后等写完所有了再分开,但是这样不仅看起来很复杂,而且很难理解,更无法显示新页面,等我分完函数,重新写了GUI以后,就可以正常的显示了。
- 打包成jar包但是无法在命令台运行,也无法双击运行
这个问题中有3个小问题,第一个问题,打包jar包的时候可能没有打包好;第二个问题,无法在命令台运行;第三个问题,双击运行闪退。
- 首先第一个问题,打包问题。先选择Export然后选择JAR file,然后选择项目,选择路径,选择Main函数入口,最后打包。
我最开始是没有设定这个主函数入口,所以无法直接调用。 - 第二个问题,在命令台无法使用。
一直都是找不到主类,我去查找了为什么但是找不到一个适合的解决方法,第一个可能是环境变量没有配置好,但是我在命令台上测试,环境变量是正确的,所以这个选项排除。第二个可能是jdk版本不够新,所以我去官网下载了17版本,重新配置环境变量后还是不行,报错原因一样,所以这个原因排除。最后一个原因,这个原因我找了很久,最后查到可能是路径没有在jar包的路径下面运行,所以我先把路径转换到jar包下的路径,然后再改变命令,改成java -jar xxx.jar,这样就可以在命令台运行了。 - 第三个问题,双击闪退问题。这个问题好像是很常见的问题,很多人都与我一样会闪退,解决方法也很多种。第一个方法,改变注册表。需要打开注册表,找到对应java的位置后将注册表中间加上-jar,然后就可以运行,但是这个方法我不适用。第二个方法,在jar包的地方写一个文本文件,写上javaw -jar %1 ,然后重命名为run.bat,然后将jar的打开方式改为run.bat,这样就可以运行了,这个方法是可以的。
- 添加成绩无法一列一列的添加
我最开始的想法的想法是通过for循环,不断的刷新面板中的信息,根据面板中的信息填写成绩,然后存入链表。但是,如果是通过for循环的话,就不会停留在前几个人物,而是直接循环到最后一个人物,然后填写,这是不对的,所以我单独写了一个新的函数,这个函数里会新建面板然后输入信息,然后修改。
6. 展望
完成的不足之处:
-
添加成绩。
我现在的添加成绩虽然可以满足大部分数据,但是如果所有的页面都新建弹出的话,数据多的话,页面会变得非常的繁杂,我希望可以改成只生成一个页面,然后之需要更新信息,就可以直接更改链表中的内容,这样会更简单,但是我还做不到。 -
使用数据库存储数据。
我现在是使用文件存储信息,但是,相对于文件,数据库肯定是更加好的,但是我对数据库这方面不是很熟悉,为了稳妥起见,还是使用了文件,当然,我会在课后对数据库去进行学习,然后争取改进我的课设。 -
没有使用更加便利快速的排序方式。
对于这个我想说,还是因为稳妥起见,因为我之前尝试过使用快排,但是因为种种原因一直在报错,当然我知道对于更多数据我的冒泡排序会非常非常的慢,但是我来不及了,课后会做一定的修正的。 -
没有实现对学生成绩的柱状图的输出。
不会,这个是真的不会,看不懂代码,这个只有在学习了相关技术之后才能实现吧,但是我现在的水平还不足以完成这方面的编写。 -
没有使用git管理自己的代码。
因为是单人作品所以就没有去做这方面的工作,当然git也是很重要的,以后和别的同学做工作的时候也是要用到的,下次会使用git来管理自己的代码,让自己向真正的程序员更近一步。 -
阿里巴巴编程规约扫描剩下一个警告。
这个我还没找到它的替代方法。
想要继续研究的方向:
- 对GUI的表格这方面要更加深入的研究。
- 对Java打包成jar文件做成桌面端应用要更加深入的学习。
- 数据库的使用。
- 画出柱状图的代码的研究。
- POI技术,争取下次实现对excel文件的读写。
- web编程技术。