前言
本项目基于qt4.8.4+sqlite3(也可换成mysql都很方便,可看前文如何进行配置),qt5版本其实更好开发。做这个项目是为了熟悉一下qt的槽和信号和控件应用。(已发布在github上面,链接在文章末尾)
主要功能
数据的增删查改,学生成绩按学期用折线图展示以及qt带来的可视化和便捷操作性。
数据库设计
简单设计了四张表。其中sc是具体到每个学生的课程和成绩表,它的两个值与学生、管理表的主键是外键约束关系。(暂时没设密码)
user表
| 字段名 | 类型 | 可空 | 字段说明 | 约束 |
|---|---|---|---|---|
| user_id | Int | No | 学生标识 | Primary key |
| user_num | Varchar(10) | No | 学生学号 | Unique key |
| user_name | Varchar(18) | No | 学生姓名 | |
| user_class | Varchar(18) | No | 学生班级 | |
| user_pro | Varchar(10) | No | 学生专业 | |
| user_sex | Char(4) | No | 学生性别 | |
| user_bi_date | Date | No | 出生日期 | |
| user_ad_date | Date | No | 入学日期 |
相关语句
create table user(user_id int not null primary key,user_num varchar(10) not null unique,user_name varchar(18) not null,user_class varchar(18) not null,user_pro varchar(10) not null,user_sex char(4) not null,user_bi_date date not null,user_ad_date date not null);
insert into user values(1,"0221123095","小明","三年二班","土木工程","男","2002-01-01","2021-09-10"),(2,"0221123096","小白","三年二班","土木工程","男","2002-09-11","2021-09-01");;
admin表
| 字段名 | 类型 | 可空 | 字段说明 | 约束 |
|---|---|---|---|---|
| admin_id | Int | No | 管理者标识 | Primary key |
| admin_num | Varchar(10) | No | 管理者编号 | Unique key |
| admin_name | Varchar(18) | No | 管理者姓名 |
create table admin(admin_id int not null primary key,admin_num varchar(10) not null unique,admin_name varchar(18) not null);
insert into admin values(1,"01","小刚");
course表
| 字段名 | 类型 | 可空 | 字段说明 | 约束 |
|---|---|---|---|---|
| course_id | Int | No | 课程标识 | Primary key |
| course_num | Varchar(10) | No | 课程课号 | Unique key |
| course_name | Varchar(40) | No | 课程名称 | |
| course_term | Varchar(40) | No | 授课时期 | |
| course_credit | Int | No | 课程学分 |
Create table course(course_id int not null primary key,course_num varchar(10) not null unique,course_name varchar(40) not null, course_term varchar(40) not null, course_credit int not null);
insert into course values(2,"43234","篮球","2021秋季学期",2);
insert into course values(1,"32132","乒乓","2021秋季学期",2), (3,"32332","羽毛球","2022春季学期",2);
insert into course values(3,"32332","羽毛球","2022春季学期",2);
sc表
| 字段名 | 类型 | 可空 | 字段说明 | 约束 |
|---|---|---|---|---|
| sc_sid | Int | No | 学生标识 | Foreign key |
| sc_cid | Int | No | 课程标识 | Foreign key |
| sc_grade | Float | No | 课程成绩 |
Create table sc(sc_sid int,sc_cid int,sc_grade float, CONSTRAINT fk_sc_sid foreign key(sc_sid) references user(user_id),CONSTRAINT fk_sc_cid foreign key(sc_cid) references course(course_id));
insert into sc values(1,1,null), (1,2,null), (1,3,null), (2,2,null), (2,3,null);
qt开发
主要运用了列表框qtlistwidget和表格框qtablewidget还有下拉框qcombobox。登陆界面成功后,将具体的用户身份id值跳入其对应的界面,界面里展示其应该被展现的信息。利用对应控件里的信号函数以及自写的相关槽函数。以下将示例下此项目的典型例子:
登录后跳转界面
if (query.next()) {
int id = query.value(0).toInt();
this->hide();
if (ui->cho_stu->isChecked()) {
StudentDialog* stu_page = new StudentDialog();
stu_page->onShow(id);
}
else {
AdminWidget* ad_page = new AdminWidget();
ad_page->maShow(id);
}
}
跳转后在Listwidget里展示相应信息
str = QString("select *from sc where sc_sid = %1;").arg(id);
query.exec(str);
vector<int> s_id;
while(query.next()){
s_id.push_back(query.value(1).toInt());
}
query.clear();
QString c_name;
QString c_credit;
for (int i = 0; i < s_id.size(); ++i) {
str = QString("SELECT course_name, course_credit from course where course_id = %1;").arg(s_id[i]);
query.exec(str);
query.next();
c_credit = query.value(1).toString();
c_name = query.value(0).toString();
c_name = QString::fromLocal8Bit("课名: ") + c_name;
c_credit = QString::fromLocal8Bit("学分:") + c_credit;
ui->m_list->addItem(c_name + " " + c_credit);
query.clear();
}
ui->m_list->adjustSize();
tablewidget单元格信息变化,首先利用槽函数void onRecorded(int, int)记录对应数据
connect(ui->tableWidget, SIGNAL(cellChanged(int, int)),
this, SLOT(onRecorded(int, int)));
再在按了更新按钮后实现在void onUpdated()中实现更新操作。
connect(ui->m_updated, SIGNAL(clicked(void)),
this, SLOT(onUpdated(void)));
void MaDialog::onUpdated(){
QString str;
SqliteDb *sqlite = SqliteDb::getInstance();
if (QSqlDatabase* db = (QSqlDatabase*)sqlite->ConnectDB("qt"))
{
bool flag = false;
str = QString("select count(*) from course;");
QSqlQuery query;
query.exec(str);
int num = 0;
if (query.next()) {
num = query.value(0).toInt();
}
query.clear();
if (ui->tableWidget->rowCount() == num) {
for(auto iter=this->rec.begin(); iter!=this->rec.end(); iter++) {
QString m_change = ui->tableWidget->item(iter->first, iter->second)->text();
int m_select = ui->tableWidget->item(iter->first, 0)->text().toInt();
if (iter->second == 2) {
str = QString("update course set course_name = '%1' where course_id = %2;").arg(m_change).arg(m_select);
}
else if (iter->second == 3) {
str = QString("update course set course_term = '%1' where course_id = %2;").arg(m_change).arg(m_select);
}
else if (iter->second == 4) {
int im_change = m_change.toInt();
str = QString("update course set course_credit = %1 where course_id = %2;").arg(im_change).arg(m_select);
}
flag = true;
}
}
else {
int temp = ui->tableWidget->rowCount() - 1;
str = QString("insert into course values(%1,'%2','%3','%4',%5);").arg(ui->tableWidget->item(temp, 0)->text().toInt()).arg(ui->tableWidget->item(temp, 1)->text()).arg(ui->tableWidget->item(temp, 2)->text()).arg(ui->tableWidget->item(temp, 3)->text()).arg(ui->tableWidget->item(temp, 4)->text().toInt());
flag = true;
}
this->rec.clear();
if (query.exec(str) == true && flag == true) {
QMessageBox message(QMessageBox::NoIcon, QString::fromLocal8Bit("学生管理"), QString::fromLocal8Bit("更新成功!"));
message.exec();
}
}
}
成果展示
学生端
教师端
课程主键是外键所以不允许删除。学号和Id都只能由系统更改,所以前两列设置为不可编辑。