Qt实现学生学籍管理系统(文件存储)
记录
19:53 2019-07-30
在小学期学c++做完课设后萌生了把写完的课设放在博客上的想法,于是,我第一篇博客诞生了。
22:32:19 2019-07-30
下棋
16:04:56 2019-07-31
开始一边划水一边写 没写
14:51:18 2019-08-01
开始认真地写
16:54:55 2019-08-04
今天一定要写三分之二
19:31:00 2019-08-04
基本写完 之后会尝试加上数据库(没有)以及数据美化
19:45:41 2019-08-31
开始美化 我是鸽子
Qt实现学生学籍管理系统(文件存储)
对Qt初步了解:点这
看一看reference:点我
(本来就不会)大部分代码都是抄的博主suvvm:https://www.cnblogs.com/suvvm/p/10723449.html(这篇文章写的好)
github:https://github.com/57one/qt-learing/tree/master/StudentStatusSystem
课设要求:对学生信息录入,对信息的增删改排,可增加其他有用的功能
可使用Qt开发框架(别人都用我能不用吗),可以使用文件或数据库(大佬都用数据库去了)
学生属性设计:姓名、学号、数学成绩、英语成绩、程序设计成绩、体育成绩、籍贯(手动存信息真的是太痛苦了)
Qt窗口设计:
- 登录界面(登录、注册、修改密码、忘记密码、退出)(这部分和学生界面设计有相似的地方,以后补充)
- 菜单界面
- 增加学生界面
- 修改学生界面(包括删除)
- 查找学生界面
- 对学生信息进行排序
项目设计:
因为我不会用数据库,而录入学生学籍又要使用省市区名,于是我尝试使用了将所有省市区写到txt文件中
我将所有的数据都录入txt文件了
录入的格式是: 行政编号 地区
之后会把文件放到网盘的
1.建立项目
建立一个空项目
之后 点下一步就创建完成了一个空项目
2.界面的建立
把我们需要的窗口都加上
在新建的项目上右键选择AddNew
选择后
这个MainControl就是用来把其他界面添加到一个QStackedLayout中(不知道的话可以看看文档 或者我下面会介绍)
之后按这样的步骤再新建LoggingWidget(登录界面)、MenuWidget(菜单界面)、AddStudentWidget(增加学生界面)、ModifyStudentWidget(修改学生界面)、SearchStudentWidget(查找学生界面)、
SortStudentWidget(学生信息排序界面)
注意要在pro文件中加上
1 QT +=widgets
2 QT +=core gui
之后在 Add new 一个main.cpp文件
main.cpp
1 #include"maincontrol.h" //下面要实例化一个MainControl对象
2 #include <QApplication>
3
4 /*QApplication类管理GUI程序的控制流和主要设置,基于Qwidget 处理Qwidget特有的初始化和结束收尾工作*/
5 //QDialog、QMainWindow都继承于Qwidget
6 /*不管任何GUI程序,不管有多少个Window,只会有一个QApplication对象
7 QApplication管理了各种各样的应用程序的广泛资源、比如默认的字体和光标*/
8 //简而言之 QApplication做了许多初始化工作,因此在其他UI对象创建前必须创建QApplication对象
9
10 int main(int argc, char *argv[])//程序的入口 main函数的2个参数 argc和argv argc是命令行的数量,argv存着命令行
11 {
12 QApplication a(argc, argv); //QApplication对象的创建 处理命令行参数
13 MainControl w; //MainControl对象的创建
14 w.show(); //利用show函数 变为可见
15 return a.exec(); //a.exec()进入事件循环 相当于把程序运行交给Qt处理,进入程序的循环状态
16 //return 0 会直接结束程序
17 }
如果不懂 a.exec()做了什么的话 可以看看:别点人家了啦
这样我们的程序就可以跑了 但啥都没有
接下来我们要做的就是设计界面 并设计界面切换 信号与槽(不明白可以看看文档)
3.界面设计
(其实这只是能看的样子,美化我以后再做)
点击对应的ui文件 进行设计
1)LoggingWidget.ui
2)MenuWidget.ui
3)AddStudentWidget.ui
4)ModifyStudentWidget.ui
5)SearchStudentWidget.ui
6)SortStudentWidget.ui
这就是最终设计(大概)
4.实现界面的切换
现在实现界面之间的切换 这就用到了Qt中的信号与槽
那先来了解一下信号与槽
先看看官方文档的解释 Signals & Slots
Qt用信号和槽代替了回调函数
简单的理解就是 用户的动作(或者说是满足某种条件)比如 点击产生了信号 这个信号传给槽函数(就是函数 接受到信号时会被调用)
比如在界面中有一个 关闭按钮 我点击后 产生了信号 与这个信号连接的关闭函数被调用(当然我提前把他们关联起来了)
信号可以由 图形界面对象发出 ,也可以由用户用 emit关键字发出信号(界面切换会用到emit)
要注意的是:槽函数的参数不多于信号的参数
首先了解一下界面切换的原理 首先我们把这么几个界面放在一个QStackedLayout中(这个QStackedLayout可以提供多界面切换,并且每次只会显示一个界面)
QStackLayout中有 AddWidget的方法 可以添加我们所需的界面(比如AddStudentWidget LoggingWidget之类的)
QStackLayout中有 一个槽函数:setCurrentIndex(int Index) 可以设置当前显示的界面 (这个Index就是你界面的标号 按照你添加界面的顺序从0开始,如果你没添加任何界面的话就是-1)
这样我们就可以通过 发射信号 来让槽函数改变当前显示界面
1)先把界面添加到一个QStackedLayout中
maincontrol.h
#ifndef MAINCONTROL_H
#define MAINCONTROL_H
#include <QWidget>
#include<QStackedLayout>
#include<QMessageBox> //用于消息提示
#include"loggingwidget.h"
#include"menuwidget.h"
#include"addstudentwidget.h"
#include"modifystudentwidget.h"
#include"searchstudentwidget.h"
#include"sortstuwidget.h"
namespace Ui {
class mainControl;
}
class mainControl : public QWidget
{
Q_OBJECT
private:
QStackedLayout *stackedLayout;
MenuWidget *menuwidget;
AddStudentWidget *addstuwidget;
ModifyStudentWidget *modifystuwidget;
SearchStudentWidget *searchstuwidget;
SortStuWidget *sortstuwidget;
LoggingWidget *loggingWidget;
public:
explicit mainControl(QWidget *parent = nullptr);
~mainControl();
private:
Ui::mainControl *ui;
};
#endif // MAINCONTROL_H
maincontrol.cpp
#include "maincontrol.h"
#include "ui_maincontrol.h"
mainControl::mainControl(QWidget *parent) :
QWidget(parent),
ui(new Ui::mainControl)
{
ui->setupUi(this); //初始化界面
stackedLayout=new QStackedLayout; //QStackedLayoutlay对象的建立
loggingWidget=new LoggingWidget;
menuwidget=new MenuWidget;
addstuwidget=new AddStudentWidget;
modifystuwidget=new ModifyStudentWidget;
searchstuwidget=new SearchStudentWidget;
sortstuwidget=new SortStuWidget;
stackedLayout->addWidget(loggingWidget); //向stackedlayout中添加界面
stackedLayout->addWidget(menuwidget);
stackedLayout->addWidget(addstuwidget);
stackedLayout->addWidget(modifystuwidget);
stackedLayout->addWidget(searchstuwidget);
stackedLayout->addWidget(sortstuwidget);
setLayout(stackedLayout); //设置界面
}
mainControl::~mainControl()
{
delete ui;
}
这样就把所需要的界面添加到QstackedLayout中了
再看看setupUi和setLayout
从初始化列表中我们可以看到 ui是Ui::mainControl的指针 注意:这个Ui::mainControl类和mainControl类是两个不同的类(废话) 我们可以在maincontrol.h中看到Ui::mainControl是定义再命名空间Ui下的类。
ui->setupUi(this) 实现了窗体上组件的创建、属性设置、信号与槽的关联。 它按照我们在qt设计器中的设计用c++代码创建组件。
关于这个setLayout 对于我的程序来说 没了它还是能跑的 但会出现界面同时存在的情况 没有达到切换界面的效果。
接下来我们就利用信号与槽实现界面的切换
我们的要求是在界面中点击pushbutton然后进行界面切换
这个点击pushbutton也可以一个信号(我们可以在ui界面中选择一个pushbutton 右键->转到槽 中看到有许多信号 )
不过这个信号并不能直接的切换界面 需要编写自己的信号函数
这个意思就是 pushbutton的信号(qt已经存在的)->一个槽函数(利用qt创建)->我们的信号(自己写的)->界面切换的槽函数
我们先在loggingwidget.h中添加一个我们自己的信号
WQ#ifndef LOGGINGWIDGET_H
#define LOGGINGWIDGET_H
#include <QWidget>
#include<QLineEdit>
namespace Ui {
class LoggingWidget;
}
class LoggingWidget : public QWidget
{
Q_OBJECT
public:
explicit LoggingWidget(QWidget *parent = nullptr);
~LoggingWidget();
signals:
void display(int number); //我们的信号
private:
Ui::LoggingWidget *ui;
};
#endif // LOGGINGWIDGET_H
我们的信号是 在pushbutton按下 后在槽函数中发出的 我们在loggingwidget.ui中找到 登录pushbutton 选择右键->转到槽 选择click() 函数 再点击ok就会自动生成一个槽函数
这个槽函数的名字是
on_btnLogging_clicked();
这个btnLogging就是我 登录pushbutton的名称
在函数定义中发射我们的信号就可以了
#include "loggingwidget.h"
#include "ui_loggingwidget.h"
LoggingWidget::LoggingWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::LoggingWidget)
{
ui->setupUi(this);
ui->UserName_Text->setPlaceholderText("请输入用户名");
ui->UserPasd_Text->setPlaceholderText("请输入密码");
}
LoggingWidget::~LoggingWidget()
{
delete ui;
}
void LoggingWidget::on_btnLogging_clicked()
{
emit display(1); //我们的信号 里面的数字是根据添加界面的顺序来的
}
这样就完成了 pushbutton的信号(qt已经存在的)->一个槽函数(利用qt创建)->我们的信号(自己写的)
接下来将的信号与槽函数连接起来
maincontrol.cpp
1 #include "maincontrol.h"
2 #include "ui_maincontrol.h"
3
4 mainControl::mainControl(QWidget *parent) :
5 QWidget(parent),
6 ui(new Ui::mainControl)
7 {
8 ui->setupUi(this); //初始化界面
9 stackedLayout=new QStackedLayout; //QStackedLayoutlay对象的建立
10 loggingWidget=new LoggingWidget;
11 menuwidget=new MenuWidget;
12 addstuwidget=new AddStudentWidget;
13 modifystuwidget=new ModifyStudentWidget;
14 searchstuwidget=new SearchStudentWidget;
15 sortstuwidget=new SortStuWidget;
16 stackedLayout->addWidget(loggingWidget); //向stackedlayout中添加界面
17 stackedLayout->addWidget(menuwidget);
18 stackedLayout->addWidget(addstuwidget);
19 stackedLayout->addWidget(modifystuwidget);
20 stackedLayout->addWidget(searchstuwidget);
21 stackedLayout->addWidget(sortstuwidget);
22 setLayout(stackedLayout); //设置界面
23 connect(loggingWidget,&LoggingWidget::display,stackedLayout,&QStackedLayout::setCurrentIndex);
24 mainControl::~mainControl()
25 {
26 delete ui;
27 }
这个connec函数将信号与槽连接
connect函数的原型 bool QObject::connect(const QObject* sender,const char * signal,const QObject * receiver,const char * member)[static]
上面23行 意思是loggingWidget 发射的display信号 会被 stackLayout 的setCurrentIndex接受到
display参数与setCurrentIndex的参数都是int型 所以setCurrenIndex可以实现切换界面
之后就是相似的实现其他界面切换(包括退出)
loggingwidget.h
1 #ifndef LOGGINGWIDGET_H
2 #define LOGGINGWIDGET_H
3
4 #include <QWidget>
5 #include<QLineEdit>
6 namespace Ui {
7 class LoggingWidget;
8 }
9
10 class LoggingWidget : public QWidget
11 {
12 Q_OBJECT
13 public:
14 explicit LoggingWidget(QWidget *parent = nullptr);
15 ~LoggingWidget();
16 signals:
17 void display(int number);
18 private slots:
19 void on_btnLogging_clicked();
20 void on_btnExit_clicked();
21
22 private:
23 Ui::LoggingWidget *ui;
24 };
25
26 #endif // LOGGINGWIDGET_H
loggingwidget.cpp
#include "loggingwidget.h"
#include "ui_loggingwidget.h"
LoggingWidget::LoggingWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::LoggingWidget)
{
ui->setupUi(this);
ui->UserName_Text->setPlaceholderText("请输入用户名");
ui->UserPasd_Text->setPlaceholderText("请输入密码");
}
LoggingWidget::~LoggingWidget()
{
delete ui;
}
void LoggingWidget::on_btnLogging_clicked()
{
emit display(1);
}
void LoggingWidget::on_btnExit_clicked()
{
QApplication::exit();
}
这个exit就是使QApplication退出主事件循环
menuwidget.h
menuwidget.cpp
addstudentwidget.h
addstudentwidget.cpp
modifystudentwidget.h
modifystudentwidget.cpp
searchstudentwidget.h
searchstudentwidget.app
sortstudentwidget.h
sortstudentwidget.cpp
这样界面的切换就实现了 接下来将每个功能做好
5.AddStudnetWidget
先实现用combox三级联动省市区
在开始的时候我已经把所有的信息都录入到文件中了
combobox有个信号currentIndexChanged 可以传递改变的text 我们可以根据text文本内容打开相应的文件
因为录入的时候是 行政编号加地区 录入的 所以省 这个类 有2个变量
province.h
1 #ifndef PROVINCE_H
2 #define PROVINCE_H
3 #include<QString>
4 class Province
5 {
6 private:
7 QString ProvinceNumber,ProvinceName;
8 public:
9 Province(){}
10 Province(QString ProvinceNumber,QString ProvinceName):ProvinceNumber(ProvinceNumber),ProvinceName(ProvinceName){}
11 QString GetProName(){return ProvinceName;}
12 QString GetProNumber(){return ProvinceNumber;}
13 };
14
15 #endif // PROVINCE_H
省 市 区 在文档中都是 行政编号加地区 所以我就没有再新建 市 类 和 区 类 直接用省的对象来 操作
把学生类也定义了 下面录入信息会用
studentinfo.h
1 #ifndef STUDENTINFO_H
2 #define STUDENTINFO_H
3 #include"QString"
4 class StudentInfo
5 {
6 private:
7 QString Name;
8 int ID,MathScore,EngScore,ProScore,PEScore;
9 QString Province,City,District;
10 public:
11 StudentInfo(){}
12 StudentInfo(QString Name,int ID,int MathScore,int EngScore,int ProScore,
13 int PEScore,QString Province,QString City,
14 QString District):Name(Name),ID(ID),MathScore(MathScore),EngScore(EngScore),ProScore(ProScore),
15 PEScore(PEScore),Province(Province),City(City),District(District){}
16 QString GetName()const{return Name;}
17 int GetID()const{return ID;}
18 int GetMathScore()const{return MathScore;}
19 int GetEngScore()const{return EngScore;}
20 int GetProScore()const{return ProScore;}
21 int GetPEScore()const{return PEScore;}
22 QString GetProvince()const{return Province;}
23 QString GetCity()const{return City;}
24 QString GetDistrict()const{return District;}
25 void SetName(QString name){Name=name;}
26 void SetMathScore(int mathScore){MathScore=mathScore;}
27 void SetEngScore(int engScore){EngScore=engScore;}
28 void SetProScoer(int proScore){ProScore=proScore;}
29 void SetPEScore(int peScore){PEScore=peScore;}
30 void SetProvince(QString province){Province=province;}
31 void SetCity(QString city){City=city;}
32 void SetDistrict(QString district){District=district;}
33 };
34 #endif // STUDENTINFO_H
addstudentwidget.h
addstudentwidget.h
1 #include "addstudentwidget.h"
2 #include "ui_addstudentwidget.h"
3
4 AddStudentWidget::AddStudentWidget(QWidget *parent) :
5 QWidget(parent),
6 ui(new Ui::AddStudentWidget)
7 {
8 ui->setupUi(this);
9 QFile file("F:\\country\\china\\provinces.txt"); // 打开省的文档
10 file.open(QIODevice::ReadOnly|QIODevice::Text); //打开方式 readonly只读 text以文本形式打开
11 if(!file.isOpen()) //判断文件打开是否成功
12 {
13 QMessageBox::about(NULL,"错误","文件打开失败");
14 return ;
15 }
16 QTextStream inp(&file); //利用QTextStream读写文件
17 QVector<Province>allProvince; //利用QVector录入行政号及地区
18 QList<QString>ProvinceList; //利用QList录入地区
19 bool have=false; //检测是否录入信息
20 while(!inp.atEnd())
21 {
22 have=true;
23 QString ProvinceNumber,ProvinceName;
24 inp>>ProvinceNumber>>ProvinceName;
25 allProvince.push_back(Province(ProvinceNumber,ProvinceName));
26 ProvinceList.append(ProvinceName);
27 }
28 if(have) //这里这个没有也可以
29 allProvince.pop_back();
30 file.close();
31 ui->Province->addItems(ProvinceList); //设置combobox的items
32 }
33
34 AddStudentWidget::~AddStudentWidget()
35 {
36 delete ui;
37 }
38
39 void AddStudentWidget::on_btnQuit_clicked()
40 {
41 emit display(1);
42 }
43
44 void AddStudentWidget::on_Province_currentIndexChanged(const QString &arg1)
45 {
46 ui->City->clear(); //清空市combobox的内容
47 QString DatAddress="F:\\country\\china\\"+arg1+"\\"+arg1+"Cities.txt"; //利用省combobox的改变来访问市文档
48 QFile file(DatAddress);
49 file.open(QIODevice::ReadOnly|QIODevice::Text);
50 if(!file.isOpen())
51 {
52 QMessageBox::about(NULL,"错误","文件打开失败");
53 return ;
54 }
55 QTextStream inp(&file);
56 QVector<Province>allProvince;
57 QList<QString>ProvinceList;
58 bool have=false;
59 while(!inp.atEnd())
60 {
61 QString ProvinceNumber,ProvinceName;
62 inp>>ProvinceNumber>>ProvinceName;
63 allProvince.push_back(Province(ProvinceNumber,ProvinceName));
64 ProvinceList.append(ProvinceName);
65 }
66 if(have)
67 allProvince.pop_back();
68 file.close();
69 ui->City->addItems(ProvinceList);
70 }
71
72 void AddStudentWidget::on_City_currentIndexChanged(const QString &arg1)
73 {
74 ui->District->clear();
75 QString DatAddress="F:\\country\\china\\"+ui->Province->currentText()+"\\"+ui->Province->currentText()+"Cities\\"+arg1+".txt";
76 QFile file(DatAddress); //利用省和市来访问区文档
77 file.open(QIODevice::ReadOnly|QIODevice::Text);
78 /*if(!file.isOpen())
79 {
80 QMessageBox::about(NULL,"错误","文件打开失败");
81 return ;
82 }*/
83 QTextStream inp(&file);
84 QVector<Province>allProvince;
85 QList<QString>ProvinceList;
86 bool have=false;
87 while(!inp.atEnd())
88 {
89 QString ProvinceNumber,ProvinceName;
90 inp>>ProvinceNumber>>ProvinceName;
91 allProvince.push_back(Province(ProvinceNumber,ProvinceName));
92 ProvinceList.append(ProvinceName);
93 }
94 if(have)
95 allProvince.pop_back();
96 file.close();
97 ui->District->addItems(ProvinceList);
98 }
99 void AddStudentWidget::on_btnAdd_clicked()
100 {
101 if(ui->Name_Text->text()==""||ui->ID_Text->text()==""||ui->Math_Text->text()==""||
102 ui->English_Text->text()==""||ui->Programming_Text->text()==""||
103 ui->PE_Text->text()=="")
104 {
105 QMessageBox::about(NULL,"错误","存在空项"); //存在空项进行报错
106 return ;
107 }
108 QFile file("StudentInfo.txt"); //打开文档 也可以使用绝对路径
109 file.open(QIODevice::WriteOnly|QIODevice::Text|QIODevice::Append);
110 while (!file.isOpen())
111 {
112 QMessageBox::about(NULL,"错误","文件打开失败");
113 return ;
114 }
115 QTextStream outp(&file);
116 outp<<ui->Name_Text->text()<<" "<<ui->ID_Text->text()<<" "<<ui->Math_Text->text()<<" "<<ui->English_Text->text()<<" "
117 <<ui->Programming_Text->text()<<" "<<ui->PE_Text->text()<<" "<<ui->Province->currentText()<<" "<<ui->City->currentText()<<
118 " "<<ui->District->currentText()<<endl;
119 file.close();
120 QMessageBox::about(NULL,"反馈","录入成功");
121 ui->Name_Text->clear(); //清空plaintext
122 ui->ID_Text->clear();
123 ui->Math_Text->clear();
124 ui->English_Text->clear();
125 ui->Programming_Text->clear();
126 ui->PE_Text->clear();
127 ui->Province->setCurrentText("北京市"); //设置为默认
128 }
学生信息录入使用 QTextStream和QFile结合的方式 QTextStream 与 IO 读写设备结合,为数据读写提供了一些方便的方法的类
其中QIODevice决定了文件的打开方式
在读入省市区时我用了QVector和QList 其实QVector没有实际运用,如果要使用行政号可能会用(以后的事)
但在使用QVectort时发现了一个问题
读入数据时 QVector使用的push_back 之后QVector进行了pop_back()(其实这里有没有无所谓pop无所谓 后面其它界面代码设计时 得有
我查询了 循环中 的atend函数 官网上是这样的
在addstudentwidget中是没有问题的
但在后面的代码中(modifystudentwidgt searchstudentwidget中缺了这个pop是不行的 会多出一行空的数据
18:54:08 2019-08-01 该问题未解决 怀疑是\r\n导致的
这样大概完成了addstudentwidget的设计
剩下的还有modifystudetwidget searchstudentwidget sortstudentwidget
这三个都是将数据先读入QVector中 然后对数据进行操作 所以可以加一个头文件 global.h和global.cpp 里面写将数据从文件读入 QVector 和将数据写入文件(modifystudentwidget会用)
global.h
1 #ifndef GLOBAL_H
2 #define GLOBAL_H
3 #include<QFile>
4 #include<QTextStream>
5 #include<QMessageBox>
6 #include"studentinfo.h"
7 class Global
8 {
9 public:
10 Global();
11 };
12 bool GetStudentInfo(QVector<StudentInfo> &allStudentInfo);
13 void WriteFile(QVector<StudentInfo>&allStudentInfo);
14 #endif // GLOBAL_H
global.cpp
1 #include "global.h"
2
3 Global::Global()
4 {
5
6 }
7 bool GetStudentInfo(QVector<StudentInfo> &allStudentInfo)
8 {
9 QFile file("StudentInfo.txt");
10 file.open(QIODevice::ReadOnly|QIODevice::Text);
11 while (!file.isOpen()) {
12 QMessageBox::about(NULL,"错误","文件打开失败");
13 return false;
14 }
15 QTextStream inp(&file);
16 bool have=false;
17 while(!inp.atEnd())
18 {
19 have=true;
20 QString name,province,city,district;
21 int id,math,english,programming,pe;
22 inp>>name>>id>>math>>english>>programming>>pe>>province>>city>>district;
23 allStudentInfo.push_back(StudentInfo(name,id,math,english,programming,pe,province,city,district));
24 }
25 if(have)
26 {
27 allStudentInfo.pop_back();
28 }
29 file.close();
30 return true;
31 }
32 void WriteFile(QVector<StudentInfo>&allStudentInfo)
33 {
34 QFile file("StudentInfo.txt");
35 file.open(QIODevice::WriteOnly|QIODevice::Text|QIODevice::Truncate);
36 while (!file.isOpen()) {
37 QMessageBox::about(NULL,"错误","文件打开失败");
38 return ;
39 }
40 QTextStream outp(&file);
41 for(auto it: allStudentInfo)
42 {
43 QMessageBox::about(NULL,"",it.GetName());
44 outp<<it.GetName()<<" "<<it.GetID()<<" "<<it.GetMathScore()<<" "<<it.GetEngScore()<<" "<<
45 it.GetProScore()<<" "<<it.GetPEScore()<<" "<<it.GetProvince()<<" "<<it.GetCity()<<" "<<it.GetDistrict()<<endl;
46 }
47 file.close();
48 }
接下来就可以 完善其他功能了
6.ModifyStudentWidget
modifystudentwidget.h
1 #ifndef SEARCHSTUDENTWIDGET_H
2 #define SEARCHSTUDENTWIDGET_H
3
4 #include <QWidget>
5 #include<QFile>
6 #include<QVector>
7 #include<QMessageBox>
8 #include<QDebug>
9 #include<QString>
10 #include"studentinfo.h"
11 namespace Ui {
12 class SearchStudentWidget;
13 }
14
15 class SearchStudentWidget : public QWidget
16 {
17 Q_OBJECT
18
19 public:
20 explicit SearchStudentWidget(QWidget *parent = nullptr);
21 ~SearchStudentWidget();
22 signals:
23 void display(int number);
24 private slots:
25 void on_btnQuit_clicked();
26
27 void on_btnSearch_clicked();
28
29 private:
30 Ui::SearchStudentWidget *ui;
31 };
32
33 #endif // SEARCHSTUDENTWIDGET_H
modifystudentwidget.cpp
1 #include "modifystudentwidget.h"
2 #include "ui_modifystudentwidget.h"
3 #include"global.h"
4 #include"province.h"
5 ModifyStudentWidget::ModifyStudentWidget(QWidget *parent) :
6 QWidget(parent),
7 ui(new Ui::ModifyStudentWidget)
8 {
9 ui->setupUi(this);
10 QFile file("F:\\country\\china\\provinces.txt");
11 file.open(QIODevice::ReadOnly|QIODevice::Text);
12 if(!file.isOpen())
13 {
14 QMessageBox::about(NULL,"错误","文件打开失败");
15 return ;
16 }
17 QTextStream inp(&file);
18 QVector<Province>allProvince;
19 QList<QString>ProvinceList;
20 bool have=false;
21 while(!inp.atEnd())
22 {
23 QString ProvinceNumber,ProvinceName;
24 inp>>ProvinceNumber>>ProvinceName;
25 allProvince.push_back(Province(ProvinceNumber,ProvinceName));
26 ProvinceList.append(ProvinceName);
27 }
28 if(have)
29 allProvince.pop_back();
30 file.close();
31 ui->Province->addItems(ProvinceList);
32 }
33
34 ModifyStudentWidget::~ModifyStudentWidget()
35 {
36 delete ui;
37 }
38
39 void ModifyStudentWidget::on_btnQuit_clicked()
40 {
41 emit display(1);
42 }
43
44 void ModifyStudentWidget::on_btnModify_clicked()
45 {
46 if(ui->Name_Text->text()==""||ui->ID_Text->text()==""||ui->Math_Text->text()==""||
47 ui->English_Text->text()==""||ui->Programming_Text->text()==""||
48 ui->PE_Text->text()=="")
49 {
50 QMessageBox::about(NULL,"错误","存在空项");
51 return ;
52 }
53 QVector<StudentInfo>allStudentInfo;
54 if(!GetStudentInfo(allStudentInfo))
55 return ;
56 bool flag=false;
57 for(QVector<StudentInfo>::iterator it=allStudentInfo.begin();it!=allStudentInfo.end();it++) //为什么没进入?????
58 { //进入了 但我啥也没改啊
59 if(it->GetID()==ui->ID_Text->text().toInt())
60 {
61 flag=true;
62 it->SetName(ui->Name_Text->text());
63 it->SetMathScore(ui->Math_Text->text().toInt());
64 it->SetEngScore(ui->English_Text->text().toInt());
65 it->SetProScoer(ui->Programming_Text->text().toInt());
66 it->SetPEScore(ui->PE_Text->text().toInt());
67 it->SetProvince(ui->Province->currentText());
68 it->SetCity(ui->City->currentText());
69 it->SetDistrict(ui->District->currentText());
70 break;
71 }
72 }
73 if(flag)
74 {
75 QMessageBox::about(NULL,"反馈","修改成功");
76 WriteFile(allStudentInfo);
77 }
78 else
79 QMessageBox::about(NULL,"反馈","id不存在");
80 ui->ID_Text->clear();
81 }
82
83 void ModifyStudentWidget::on_btnDelete_clicked()
84 {
85
86 if(ui->ID_Text->text()=="")
87 {
88 QMessageBox::about(NULL,"错误","id不得为空");
89 return ;
90 }
91 QVector<StudentInfo>allStudentInfo;
92 if(!GetStudentInfo(allStudentInfo))
93 return ;
94 bool flag=false;
95 for(QVector<StudentInfo>::iterator it=allStudentInfo.begin();it!=allStudentInfo.end();it++)
96 {
97 if(it->GetID()==ui->ID_Text->text().toInt())
98 {
99 flag=true;
100 allStudentInfo.erase(it);
101 break;
102 }
103 }
104 if(flag)
105 {
106 QMessageBox::about(NULL,"反馈","删除成功");
107 WriteFile(allStudentInfo);
108 }
109 else
110 QMessageBox::about(NULL,"反馈","id不存在");
111 ui->ID_Text->clear();
112 }
113
114 void ModifyStudentWidget::on_Province_currentIndexChanged(const QString &arg1)
115 {
116 ui->City->clear();
117 QString DatAddress="F:\\country\\china\\"+arg1+"\\"+arg1+"Cities.txt";
118 QFile file(DatAddress);
119 file.open(QIODevice::ReadOnly|QIODevice::Text);
120 if(!file.isOpen())
121 {
122 QMessageBox::about(NULL,"错误","文件打开失败");
123 return ;
124 }
125 QTextStream inp(&file);
126 QVector<Province>allProvince;
127 QList<QString>ProvinceList;
128 bool have=false;
129 while(!inp.atEnd())
130 {
131 QString ProvinceNumber,ProvinceName;
132 inp>>ProvinceNumber>>ProvinceName;
133 allProvince.push_back(Province(ProvinceNumber,ProvinceName));
134 ProvinceList.append(ProvinceName);
135 }
136 if(have)
137 allProvince.pop_back();
138 file.close();
139 ui->City->addItems(ProvinceList);
140 }
141
142 void ModifyStudentWidget::on_City_currentIndexChanged(const QString &arg1)
143 {
144 ui->District->clear();
145 QString DatAddress="F:\\country\\china\\"+ui->Province->currentText()+"\\"+ui->Province->currentText()+"Cities\\"+arg1+".txt";
146 QFile file(DatAddress);
147 file.open(QIODevice::ReadOnly|QIODevice::Text);
148 /*if(!file.isOpen())
149 {
150 QMessageBox::about(NULL,"错误","文件打开失败");
151 return ;
152 }*/
153 QTextStream inp(&file);
154 QVector<Province>allProvince;
155 QList<QString>ProvinceList;
156 bool have=false;
157 while(!inp.atEnd())
158 {
159 QString ProvinceNumber,ProvinceName;
160 inp>>ProvinceNumber>>ProvinceName;
161 allProvince.push_back(Province(ProvinceNumber,ProvinceName));
162 ProvinceList.append(ProvinceName);
163 }
164 if(have)
165 allProvince.pop_back();
166 file.close();
167 ui->District->addItems(ProvinceList);
168 }
7.SearchStudentWidget
searchstudentwidget.h
1 #ifndef SEARCHSTUDENTWIDGET_H
2 #define SEARCHSTUDENTWIDGET_H
3
4 #include <QWidget>
5 #include<QFile>
6 #include<QVector>
7 #include<QMessageBox>
8 #include<QDebug>
9 #include<QString>
10 #include"studentinfo.h"
11 namespace Ui {
12 class SearchStudentWidget;
13 }
14
15 class SearchStudentWidget : public QWidget
16 {
17 Q_OBJECT
18
19 public:
20 explicit SearchStudentWidget(QWidget *parent = nullptr);
21 ~SearchStudentWidget();
22 signals:
23 void display(int number);
24 private slots:
25 void on_btnQuit_clicked();
26
27 void on_btnSearch_clicked();
28
29 private:
30 Ui::SearchStudentWidget *ui;
31 };
32
33 #endif // SEARCHSTUDENTWIDGET_H
searchstudentwidget.cpp
1 #include "searchstudentwidget.h"
2 #include "ui_searchstudentwidget.h"
3 #include "global.h"
4
5 SearchStudentWidget::SearchStudentWidget(QWidget *parent) :
6 QWidget(parent),
7 ui(new Ui::SearchStudentWidget)
8 {
9 ui->setupUi(this);
10 }
11
12 SearchStudentWidget::~SearchStudentWidget()
13 {
14 delete ui;
15 }
16
17 void SearchStudentWidget::on_btnQuit_clicked()
18 {
19 emit display(1);
20 }
21
22 void SearchStudentWidget::on_btnSearch_clicked()
23 {
24 if(ui->ID_Text->text()=="")
25 {
26 QMessageBox::about(NULL,"反馈","id为空");
27 return ;
28 }
29 QVector<StudentInfo>allStudentInfo;
30 if(!GetStudentInfo(allStudentInfo))
31 return ;
32 bool flag=false;
33 for(QVector<StudentInfo>::iterator it=allStudentInfo.begin();it!=allStudentInfo.end();it++)
34 {
35 if(it->GetID()==ui->ID_Text->text().toInt())
36 {
37 flag=true;
38 ui->Name_Label->setText(it->GetName());
39 ui->Math_Label->setText(QString::number(it->GetMathScore()));
40 ui->Eng_Label->setText(QString::number(it->GetEngScore()));
41 ui->Pro_Label->setText(QString::number(it->GetProScore()));
42 ui->PE_Label->setText(QString::number(it->GetPEScore()));
43 ui->Province->setText(it->GetProvince());
44 ui->City->setText(it->GetCity());
45 ui->District->setText(it->GetDistrict());
46 break;
47 }
48 }
49 if(flag)
50 QMessageBox::about(NULL,"反馈","查找成功");
51 else
52 QMessageBox::about(NULL,"反馈","id不存在");
53
54 }
8.SortStudentWidget
sortstudentwidget.h
1 #ifndef SORTSTUWIDGET_H
2 #define SORTSTUWIDGET_H
3
4 #include <QWidget>
5 #include<QFile>
6 #include<QVector>
7 #include<QMessageBox>
8 #include<QDebug>
9 #include<QButtonGroup>
10 #include<QtAlgorithms>
11 #include<QString>
12 #include<QTableWidgetItem>
13 #include"studentinfo.h"
14 namespace Ui {
15 class SortStuWidget;
16 }
17
18 class SortStuWidget : public QWidget
19 {
20 Q_OBJECT
21 private:
22 QButtonGroup *buttonGroup;
23 QStringList stringList;
24 public:
25 explicit SortStuWidget(QWidget *parent = nullptr);
26 ~SortStuWidget();
27 signals:
28 void display(int number);
29 private slots:
30 void on_pushButton_2_clicked();
31
32 void on_btnSort_clicked();
33
34 private:
35 Ui::SortStuWidget *ui;
36 };
37
38 #endif // SORTSTUWIDGET_H
sortstudentwidget.cpp
1 #include "sortstudentwidget.h"
2 #include "ui_sortstuwidget.h"
3 #include"global.h"
4 SortStuWidget::SortStuWidget(QWidget *parent) :
5 QWidget(parent),
6 ui(new Ui::SortStuWidget)
7 {
8 ui->setupUi(this);
9 buttonGroup=new QButtonGroup;
10 buttonGroup->addButton(ui->rbtnMath,0);
11 buttonGroup->addButton(ui->rbtnEnglish,1);
12 buttonGroup->addButton(ui->rbtnProgramming,2);
13 buttonGroup->addButton(ui->rbtnPE,3);
14 buttonGroup->addButton(ui->rbtnProvince,4);
15 buttonGroup->addButton(ui->rbtnID,5);
16 buttonGroup->setExclusive(true);
17 ui->tableWidget->setColumnCount(9);
18 stringList<<tr("姓名")<<tr("学号")<<tr("数学成绩")<<("英语成绩")<<tr("程序设计成绩")<<tr("体育成绩")<<tr("省")<<tr("市")<<tr("区");
19 ui->tableWidget->setHorizontalHeaderLabels(stringList);
20 ui->tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
21 ui->tableWidget->setRowCount(1);
22 }
23
24 SortStuWidget::~SortStuWidget()
25 {
26 delete ui;
27 }
28
29 void SortStuWidget::on_pushButton_2_clicked()
30 {
31 emit display(1);
32 ui->tableWidget->clearContents();
33 ui->tableWidget->setRowCount(1);
34 }
35 bool cmp_Math(const StudentInfo &a,const StudentInfo &b)
36 {
37 return a.GetMathScore()>b.GetMathScore();
38 }
39 bool cmp_English(const StudentInfo &a,const StudentInfo &b)
40 {
41 return a.GetEngScore()>b.GetEngScore();
42 }
43 bool cmp_Programming(const StudentInfo &a,const StudentInfo &b)
44 {
45 return a.GetProScore()>b.GetProScore();
46 }
47 bool cmp_PE(const StudentInfo &a,const StudentInfo &b)
48 {
49 return a.GetPEScore()>b.GetPEScore();
50 }
51 bool cmp_ID(const StudentInfo &a,const StudentInfo &b)
52 {
53 return a.GetID()>b.GetID();
54 }
55 bool cmp_Province(const StudentInfo &a,const StudentInfo &b)
56 {
57 return a.GetProvince()>b.GetProvince();
58 }
59 void SortStuWidget::on_btnSort_clicked()
60 {
61 QVector<StudentInfo>allStudentInfo;
62 if(!GetStudentInfo(allStudentInfo))
63 return ;
64 int tag=buttonGroup->checkedId();
65 switch (tag)
66 {
67 case 0:std::sort(allStudentInfo.begin(),allStudentInfo.end(),cmp_Math);break;
68 case 1:std::sort(allStudentInfo.begin(),allStudentInfo.end(),cmp_English);break;
69 case 2:std::sort(allStudentInfo.begin(),allStudentInfo.end(),cmp_Programming);break;
70 case 3:std::sort(allStudentInfo.begin(),allStudentInfo.end(),cmp_PE);break;
71 case 4:std::sort(allStudentInfo.begin(),allStudentInfo.end(),cmp_Province);break;
72 case 5:std::sort(allStudentInfo.begin(),allStudentInfo.end(),cmp_ID);break;
73 }
74 ui->tableWidget->setSortingEnabled(false);
75 ui->tableWidget->setRowCount(allStudentInfo.size()); //设置行数与学生数相同 否则添加后显示不出来
76 for(int i=0;i<allStudentInfo.size();i++)
77 {
78 ui->tableWidget->setItem(i,0,new QTableWidgetItem(allStudentInfo.at(i).GetName()));
79 ui->tableWidget->setItem(i,1,new QTableWidgetItem(QString::number(allStudentInfo.at(i).GetID())));
80 ui->tableWidget->setItem(i,2,new QTableWidgetItem(QString::number(allStudentInfo.at(i).GetMathScore())));
81 ui->tableWidget->setItem(i,3,new QTableWidgetItem(QString::number(allStudentInfo.at(i).GetEngScore())));
82 ui->tableWidget->setItem(i,4,new QTableWidgetItem(QString::number(allStudentInfo.at(i).GetProScore())));
83 ui->tableWidget->setItem(i,5,new QTableWidgetItem(QString::number(allStudentInfo.at(i).GetPEScore())));
84 ui->tableWidget->setItem(i,6,new QTableWidgetItem(allStudentInfo.at(i).GetProvince()));
85 ui->tableWidget->setItem(i,7,new QTableWidgetItem(allStudentInfo.at(i).GetCity()));
86 ui->tableWidget->setItem(i,8,new QTableWidgetItem(allStudentInfo.at(i).GetDistrict()));
87 }
88 ui->tableWidget->setSortingEnabled(true);
89 }
这样基本完成了学生学籍管理系统
声明:我这个大部分都抄了博主suvvm的 Qt5——从零开始的学生管理系统 而且我写的也没有该博主详细
美化的话 听说qss和css差不多 (不一样也没关系 反正我都不会)
先在网上找了在哪写QSS:具体教程的话:https://blog.csdn.net/kidults/article/details/53482971
具体的我就不写了(其实是不会) 大部分网上都有例子
美化后的:
当然 还存在一些bug(比如上图中horizontalHeader就有问题) 课设上的要求也没全完成
不过 美化就这样了(比不上大佬的美化) 凑合看吧