资讯动态

Qt学生信息管理系统源码解析:C++与SQLite从登录到成绩分析

发布时间:2026/10/22 14:58:43 来源:尧图企业网站定制
简介基于Qt的学生信息管理系统是一份面向高校课程设计与期末大作业的完整工程源码包含教师端与学生端。教师端支持学生信息增删查改、班级成绩分析学生端可查看个人成绩功能覆盖常见的教务管理场景既适合初学者将其作为综合练手项目也适合毕业设计时在现有框架上做二次开发。压缩包共70个文件核心代码为17个cpp源文件、14个h头文件另有5个ui界面设计文件分别承载业务逻辑、类声明和窗口布局同时带有release、debug编译目录及exe可执行程序下载后无需配置环境即可直接运行查看效果。工程基于Qt 5.14构建内置SystemDatabase.db数据库与README说明主程序及各业务窗口均独立成模块信号槽、表格展示、成绩统计等实现都比较清晰可方便地按功能模块阅读与复用。已有414人浏览学习对于希望掌握Qt界面开发、数据库读写和成绩分析流程的开发者而言这是一份结构完整、可直接参考的项目源码尤其适合作为课程设计或大作业的起步模板。1. 先搞清楚这份 Qt 学生信息管理系统能干什么再决定要不要下载期末季收到一份基于 Qt 的学生信息管理系统源码压缩包里是一套典型的 C 管理系统教师端能对学生信息做增删查改还能按班级做成绩分析学生端只能登录后查自己的成绩看不到其他学生的数据。底层用 SQLite 存数据界面直接用 Qt Designer 拖出来的整体结构非常适合拿来当课程设计、期末大作业也适合想学 Qt 多窗口开发的人做二次开发。拆包之前我先确认了 Qt 版本和构建方式读了一遍工程文件才动手编译。下面从工程结构、功能实现、坑这三个方面把这份源码完整过一遍。2. 工程结构和技术选型文件、数据表、编译方式三条线先理清拿到 Qt 项目的压缩包第一件事不是打开某个 .cpp 就开始读而是先看文件清单和 .pro 工程文件。这个项目的源码量不大但混着构建目录里自动生成的文件新手容易看晕。我拆这类资源有几个固定步骤先找工程文件、再找数据库、最后看 ui 文件和 slot 函数命名这套顺序能让你少走很多弯路。2.1 源码文件按职责划分哪几个文件是真正要看的压缩包里能看到一堆文件其中带 .cpp、.h、.ui 的是源码核心代码集中在几个窗口类里。整理一下就是这几类文件/目录职责StuInfo_Manage_System.proqmake 工程文件声明模块、源码文件和生成的 exe 名称main.cpp程序入口创建 QApplication 并启动登录窗口global.h / global.cpp全局声明通常放数据库对象和公共函数mainwindow.ui / mainwindow.cpp主登录窗口负责角色切换teacher_window.ui / teacher_window.cpp教师端主界面增删查改和成绩分析addstudent_window.ui / addstudent_window.cpp添加或编辑学生信息的表单窗口manage_window.ui / manage_window.cpp管理班级或学生列表的窗口student_window.ui / student_window.cpp学生端成绩查看窗口setIcon.qrcQt 资源文件把 icon.png 编译进程序设置窗口图标SystemDatabase.dbSQLite 数据库文件所有学生和成绩数据都存在这里构建目录里还有 ui_xx.h、Makefile、object_script 这些全是 Qt Creator 和 qmake 自动生成的不要手动改。ui_xx.h 是 .ui 文件被编译器转换出来的头文件内容是界面对象的声明你只要连接好信号槽就不需要直接操作它。2.2 通读数据表设计搞清楚 SystemDatabase.db 里存了什么这个系统用的是 SQLite数据库文件就在工程根目录下。按管理系统的需求来推断至少应该有两张核心表学生信息表和成绩表。学生表常见字段是学号、姓名、班级、性别、联系方式成绩表主要存学号、科目、分数、考试时间。数据表之间的关联靠学号字段SQL 里用 JOIN 把两张表关联起来做班级成绩分析。如果你拿到源码后发现打不开数据库可以用 SQLite 工具直接打开 SystemDatabase.db 看表结构也可以用 QSqlQuery 在程序里执行查询。我一般会把关键表结构写成建表语句放进去方便重建数据。比如学生表大概是这样的结构CREATE TABLE IF NOT EXISTS student ( id INTEGER PRIMARY KEY AUTOINCREMENT, student_id TEXT NOT NULL UNIQUE, name TEXT NOT NULL, class_name TEXT NOT NULL, gender TEXT, phone TEXT ); CREATE TABLE IF NOT EXISTS score ( id INTEGER PRIMARY KEY AUTOINCREMENT, student_id TEXT NOT NULL, subject TEXT NOT NULL, score REAL NOT NULL, exam_time TEXT );这里用student_id做关联条件学生表里这个字段加了 UNIQUE 约束避免重复学号。分数用 REAL 类型存储小数成绩没问题。注意score REAL在 SQLite 中也能存整数但计算平均分时会自动转成浮点数排序和聚合更安全。很多做课程设计的人会把学生信息和成绩塞在同一张表里后面做班级分析时统计就会乱所以拆两张表是合理做法。2.3 编译运行的两种姿势Qt Creator 打开 .pro 最省事这个项目用的是 Qt 5.14.2配的是 MinGW 32 位编译器。你机器上如果是 64 位系统直接跑 32 位编译出来的 exe 完全没问题但编译链接时编译器位数要匹配。打开方式很简单先启动 Qt Creator把 .pro 文件拖进去它会自动识别工程并加载项目配置然后选择构建套件点运行。# 在项目根目录下手动执行也可以 qmake StuInfo_Manage_System.pro mingw32-makeqmake的职责是读取 .pro 文件生成 Makefile 和必要的 ui_xx.h 头文件。mingw32-make是 Qt 自带的构建工具也可以直接按键盘上的 CtrlShiftB 在 IDE 里构建。常见的问题是如果项目用了 SQLite 模块.pro 文件必须声明QT sql否则编译时会报“找不到 QSqlDatabase”。做法是在 .pro 文件里加上QT core gui sql greaterThan(QT_MAJOR_VERSION, 4): QT widgets加了sql才能链接到 Qt 的 SQL 驱动模块。发布时还要把 Qt 的 dll 一起带上不然换台电脑运行会提示“缺少 Qt5Core.dll”这时候用自带的 windeployqt 工具就能自动收集依赖。3. 教师端功能拆解登录跳转、增删查改、成绩分析三条主线教师端是这个系统的重头戏文件里的 teacher_window.cpp 和 manage_window.cpp 承担了大部分业务。我对这类界面的拆法很简单先看构造函数里连接了哪些按钮再看每个槽函数里执行的 SQL 语句最后把界面刷新函数串起来。这样基本能还原出完整的逻辑。3.1 登录窗口到教师端角色判定怎么做主窗口 mainwindow.ui 是一个登录页面输入账号密码后程序会根据角色信息跳转到不同窗口。常见做法是全局变量里存一个当前用户身份登录成功后判断身份再用show()打开对应窗口。下面这段代码就是这个思路// main.cpp 入口只负责初始化和显示登录窗口 #include QApplication #include global.h #include mainwindow.h int main(int argc, char *argv[]) { QApplication app(argc, argv); Global::initDatabase(); // 打开 SQLite 数据库 MainWindow login; login.show(); return app.exec(); }这段代码里Global::initDatabase()是从 global.cpp 里调用的公共初始化函数作用就是把 QSqlDatabase 对象加进连接池并打开数据库。把数据库初始化放在 main 函数开头比在每个窗口里重复调用好维护得多。登录窗口验证成功后teacher_window 或 student_window 才被创建。跳转细节经常写在 mainwindow.cpp 的某个按钮点击槽里大概逻辑是if (role teacher) { TeacherWindow *w new TeacherWindow; w-show(); this-close(); } else if (role student) { StudentWindow *w new StudentWindow; w-show(); this-close(); }注意这里用的是new动态分配窗口对象因为this-close()之后如果窗口变量是栈上的函数返回时就会被析构新窗口还没显示就没了。动态分配后窗口由 Qt 的事件循环管理关闭窗口时自动释放这就是多窗口切换最常见的坑之一。3.2 学生信息增删查改输入校验、SQL 预处理、表格刷新缺一不可教师端页面上一般有几个输入框和一个按钮分别负责添加、删除、修改、查询。添加学生时如果学号为空或者已经存在最好在 SQL 执行前就拦住避免数据库报错。我用 QSqlQuery 的 prepare 方式写添加逻辑void TeacherWindow::on_addButton_clicked() { QString id ui-idEdit-text().trimmed(); QString name ui-nameEdit-text().trimmed(); QString cls ui-classEdit-text().trimmed(); if (id.isEmpty() || name.isEmpty()) { QMessageBox::warning(this, 输入错误, 学号和姓名不能为空); return; } QSqlQuery query; query.prepare(INSERT INTO student (student_id, name, class_name) VALUES (?, ?, ?)); query.addBindValue(id); query.addBindValue(name); query.addBindValue(cls); if (!query.exec()) { QMessageBox::warning(this, 添加失败, query.lastError().text()); return; } refreshTable(); // 重新查询并更新表格 }这段代码的关键点是prepare和addBindValue。直接用字符串拼接 SQL 容易出错比如学号里带引号时会破坏语句结构用预处理参数既能避免这类问题也能防止 SQL 注入风险。.trimmed()去掉首尾空格避免用户输入多余空格造成数据不统一。添加失败时一定要弹窗显示lastError().text()否则出问题后完全无从排查。删除和修改的逻辑和添加类似删除先确认选中行再执行 DELETE修改则先查出原记录填充到 addstudent_window 表单里保存时执行 UPDATE。教师端还经常遇到的一个需求是模糊查询比如按班级或姓名过滤。可以用 LIKE 拼接但拼接时注意百分号的位置SELECT * FROM student WHERE class_name LIKE % || ? || %如果只在?外面加%...%是不行的SQLite 的拼接要用双竖线。班级分析功能里筛选数据时也会用到相同写法。3.3 班级成绩分析聚合查询一次算平均分、最高分、最低分、人数成绩分析是这个项目最值得写进答辩报告的功能点。它要把成绩表按班级分组算出每个班的平均分、最高分、最低分、总人数再看看有没有及格率。SQL 聚合查询能在一个语句里完成void TeacherWindow::loadClassAnalysis() { QSqlQuery query; query.prepare( SELECT s.class_name, COUNT(DISTINCT s.student_id), ROUND(AVG(sc.score), 2), MAX(sc.score), MIN(sc.score) FROM student s JOIN score sc ON s.student_id sc.student_id GROUP BY s.class_name ); if (!query.exec()) { qDebug() query.lastError().text(); return; } int row 0; while (query.next()) { // 把结果填充到表格控件里 } }这里用JOIN把学生表和成绩表关联起来GROUP BY s.class_name按班级分组。聚合函数AVG算平均分MAX和MIN找最高最低分COUNT(DISTINCT student_id)统计班级总人数自动去掉同一个学生的多条重复记录。ROUND(..., 2)把平均分保留两位小数表格显示比较整洁。GROUP BY 之后不能再查未分组的普通字段只能查聚合函数和分组字段这个点写进课程设计报告里能解释清楚。4. 学生端功能拆解只能查成绩的权限边界怎么控制学生端在业务上比教师端简单但简单不等于可以粗糙。学生端要解决的问题是登录后看不到教师端入口查询数据时只能查自己的成绩。这两条没做好系统就存在权限漏洞。4.1 登录身份传到学生窗口用全局变量保存当前登录账号学生登录成功后程序要把当前学号存下来学生窗口查询时才好用。常见做法是在 global.h 里声明一个QString currentStudentId;或currentUserRole;登录成功时赋值其他窗口读取这个全局变量。// global.h #ifndef GLOBAL_H #define GLOBAL_H #include QString extern QString currentUserId; // 当前登录学生的学号 extern QString currentUserRole; // 角色teacher / student #endif在mainwindow.cpp登录按钮槽里验证通过后把输入框里的学号和密码对应的角色写进这两个变量再打开新窗口。这里用 extern 全局变量是 Qt 小项目常见做法方便但要注意多窗口同时存在时全局变量容易被其他地方不小心改动如果你做的是多文档项目建议用单例模式或者把登录信息封装成结构体传给窗口构造函数。4.2 查询成绩的过滤条件WHERE 条件必须跟当前学号绑定学生窗口的查询 SQL 不能是“查所有”必须把currentUserId作为查询条件。点击查询按钮后按科目或时间筛选SQL 大概是void StudentWindow::on_queryButton_clicked() { QString subject ui-subjectCombo-currentText(); QSqlQuery query; query.prepare( SELECT subject, score, exam_time FROM score WHERE student_id ? ); query.addBindValue(currentUserId); if (!query.exec()) { qDebug() query.lastError().text(); return; } while (query.next()) { // 将查询结果写入 QTableWidget 或 QTableView 的对应行 } }如果用户在下拉框里选择具体科目WHERE条件后面再加一句AND subject ?同时绑定科目名称。关键是student_id一定不能来自界面输入哪怕界面上有输入框也不要让你能随意查别人的成绩。安全控制最简单有效的方式就是过滤条件直接引用全局登录变量前端没有传“要查谁”的入口。4.3 表格只读设置别让学生把成绩改成别的值学生端的 QTableWidget 默认是可以双击编辑的如果不关掉编辑学生就能把界面上的成绩改掉。虽然改的只是内存里的显示不会改到数据库但看着和真正的业务逻辑冲突。所以构造函数里要强制设置表格只读ui-scoreTable-setEditTriggers(QAbstractItemView::NoEditTriggers); ui-scoreTable-setSelectionBehavior(QAbstractItemView::SelectRows); ui-scoreTable-setSelectionMode(QAbstractItemView::SingleSelection);setEditTriggers传入NoEditTriggers后所有单元格都不能被编辑。setSelectionBehavior设置为整行选中的作用是点击任意单元格都会选中整行视觉效果更像成绩单。最后一行SingleSelection限制只能选中一行避免误操作多选。5. 编译和运行避坑五条高频翻车记录这类 Qt 项目源码本身能跑但在不同机器上打开会遇到一堆环境问题。下面这几条是我反复见过的问题按“现象 → 原因 → 解决”列出来遇到时对照处理就行。5.1 编译报错找不到 ui_xx.h 头文件现象编译工程时提示fatal error: ui_student_window.h: No such file or directory。原因ui_student_window.h 是由 student_window.ui 文件在编译过程中自动生成的这个生成动作依赖 qmake 执行。如果只把 .ui 文件加进工程但没有用 qmake 重新生成 Makefile编译器就找不到对应的头文件。解决在 Qt Creator 里右键工程根节点选择“执行 qmake”然后重新构建。如果还不行手动把工程目录下的.pro.user文件删掉再重新打开工程让 Qt Creator 重新解析一遍。删除 .pro.user 文件不会影响源码它只是本机的 IDE 配置文件。5.2 中文显示乱码按钮文字全是问号或乱码现象编译后的程序运行时所有中文按钮文字、表格列头显示成乱码。原因源码文件保存的编码和编译器默认读取的编码不一致。项目源码常用 UTF-8但 Windows 上 MinGW 编译器默认按本地代码页读源码这就会导致中文字符串在编译时被错误解析。解决在 .pro 文件里指定源码编码或者在包含中文的 cpp 文件开头加编译指令。优先建议统一用 UTF-8 保存所有源文件并在 main.cpp 的main函数开头调用#include QTextCodec QTextCodec::setCodecForLocale(QTextCodec::codecForName(UTF-8));这行代码的意思是把 Qt 内部处理字符串时使用的本地编码设置成 UTF-8保证读取界面文本时不会转成错误编码。有些项目中文字符串写在代码里如果还是乱码就用记事本把文件另存为 UTF-8 编码格式重新编译。5.3 数据库打不开提示 database is locked 或 unable to open现象程序启动后执行查询时报unable to open database file或者操作数据库时提示database is locked。原因SQLite 数据库在程序启动时如果使用了相对路径SystemDatabase.db实际运行目录不同程序在错误的目录里找数据库。另外如果同时多个窗口或线程打开同一个数据库文件SQLite 会锁定文件。解决统一用绝对路径打开数据库尤其当程序发布到别的目录时。路径拼接方式QString dbPath QCoreApplication::applicationDirPath() /SystemDatabase.db; db.setDatabaseName(dbPath);applicationDirPath()返回当前程序 exe 所在目录。不要直接在路径前面拼一个写死的目录字符串发布后目录变了就要改代码。还要保证整个程序里只调用一次QSqlDatabase::addDatabase()后续窗口都用同一个连接。5.4 登录成功后新窗口一闪而过程序直接退出现象点击登录按钮看到一个窗口闪了一下程序就结束了。原因登录窗口的按钮槽里把旧窗口关闭但新窗口对象建在栈上也就是普通的局部变量。函数执行完栈变量析构窗口被销毁所以一闪而过。这不是 Qt 的 Bug是对象生命周期没管好。解决新窗口用new创建并且不给它指定父对象parent。例如TeacherWindow *w new TeacherWindow; w-show();如果设置w-setParent(this)新窗口会跟随登录窗口关闭而关闭所以不建议这样写。窗口关闭时 Qt 会自动释放动态分配的对象前提是没有手动 delete。5.5 链接报错minGW 和 MSVC 混着编现象换了一台电脑重新编译时报一大堆链接错误提示undefined reference to。原因项目里的 .pro.user 文件记录了原来机器上用的构建套件比如原来是 MinGW 编译你现在用 MSVC 打开旧的 Makefile 和中间文件还留着两者混用导致链接失败。解决先把工程目录下Makefile、Makefile.Debug、Makefile.Release和构建目录里的中间文件全部删掉再右键工程选择“执行 qmake”重新生成。最好把 .pro.user 也删掉让 Qt Creator 重新匹配当前的编译器。这里提醒一句就算编译器类型一致从 Debug 切到 Release 也建议先 clean 再 rebuild。6. 把项目往答辩或交付方向再推一步三个可落地的增强手段如果只是把代码跑通这项目能交差但拿不到高分。我给这类管理系统做增强时通常会补数据可视化、数据导出、发布打包三个方向按半天到一天的时间成本递增。下面挑两个性价比最高的说。6.1 批量造演示数据避免现场录入太尴尬上台演示时来回输入几条学生数据观感很差。更好的做法是在数据库脚本里一次性插入几十条成绩数据。我通常在项目里放一个init_data.sql用事务批量导入BEGIN; INSERT INTO student (student_id, name, class_name, gender) VALUES (2024001, 张三, 计算机2401, 男), (2024002, 李四, 计算机2401, 女); INSERT INTO score (student_id, subject, score, exam_time) VALUES (2024001, C语言, 88, 2025-01-10), (2024001, 数据结构, 79, 2025-01-12), (2024002, C语言, 92, 2025-01-10); COMMIT;用BEGIN和COMMIT包起来的目的是只要中间一条失败整批回滚不会出现学生有但成绩拉不出来的半吊子状态。演示时再写一个下拉框筛选班级点一下就能看到成绩分析图形变化比空表运行有说服力得多。6.2 导出一份班级成绩 CSVExcel 能直接打开这个功能很多老师验收时会点。在教师端加一个“导出当前分析结果”按钮调用下面这段逻辑void TeacherWindow::exportCsv() { QFile file(class_score.csv); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { return; } QTextStream out(file); out.setCodec(UTF-8); out QString::fromLocal8Bit(\xEF\xBB\xBF); // UTF-8 BOM out 班级,平均分,最高分,最低分,人数\n; // 查询分析结果并写入文件 }写入\xEF\xBB\xBF是 UTF-8 的 BOM 头不加这个头Excel 打开 CSV 会按本地编码读中文容易乱码。文件保存路径建议用默认的当前目录并弹一个 QMessageBox 提示导出成功比静默完成更友好。发布前最后一步是用windeployqt把 Qt 运行库收集齐命令是windeployqt StuInfo_Manage_System.exe这个工具会自动把 Qt5Core.dll、Qt5Widgets.dll、Qt5Sql.dll 以及对应插件目录复制到 exe 旁边。发布目录里必须带着sqldrivers/qsqlite.dll不然换台干净的电脑就报“Driver not loaded”这是我当初第一次打包翻车的地方。从那以后我每次拿到这类 Qt 项目源码都是先确认好 Qt 版本和编译器位数再走一遍 qmake、构建、运行、导出依赖四步流程。这套流程看着笨但最能压住环境坑。希望这份拆包记录帮到你省下几个晚上的折腾时间。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑