
简介这份资源是面向高校计算机相关专业学生的课程设计大作业完整项目——机房预约系统采用C与QT框架开发后端接入MySQL数据库适合正在准备毕业设计、C语言或C课程设计的学习者参考与二次开发。项目难度适中源码均经本地编译验证可运行按文档配置好环境即可启动能帮助读者快速理解桌面端管理系统的整体架构与实现思路。压缩包共47个文件约2.8MB以h头文件与cpp源文件为核心配合ui界面文件、pro工程配置、Makefile构建脚本及README说明文档覆盖登录、学生、教师、管理员等多角色模块目录结构清晰便于按功能模块检索学习。目前已有75人学习下载。读者可从中获取完整的项目源码、数据库连接与界面交互实现方案以及可复用的QT工程组织方式为课程设计答辩与后续开发提供扎实参考。1. 机房预约系统拆包一份能跑起来的 QTMySQL 课设长什么样课程设计最怕的不是题目难而是拿到一份源码编译报错、数据库连不上、界面打不开最后连答辩都撑不过去。这份「机房预约系统QTMySQL」的压缩包解压后能看到 orderRoomSystem-master 目录里面是完整的 QT 工程文件ordersystem.pro、main.cpp、login.cpp、student.cpp、teacher.cpp、manager.cpp配套的 .ui 界面文件和 .h 头文件一应俱全还有 Makefile、Makefile.Debug、Makefile.Release 和 object_script 文件说明它在本地至少完整编译过一轮。数据库层用 connection.h 统一管理连接业务层按角色拆成学生、教师、管理员三套逻辑登录入口在 login.cpp主窗口按权限分流。适合正在做 C 课程设计、毕业设计或者想找一个带完整 UI 和数据库交互的 QT 练手项目的人。它解决的核心问题是给你一个结构清晰、角色分明、能直接跑通的预约系统骨架而不是一堆散装代码。2. 环境搭建与工程加载从 .pro 到第一个可运行窗口2.1 QT 版本与编译器选型这份工程用的是 qmake 构建体系.pro 文件里没有引入 CMake所以 QT Creator 打开就能识别。从 Makefile 的命名和 object_script 的路径来看它大概率是在 Windows 下用 MSVC 或者 MinGW 编译的。我一般会先确认两件事QT 版本和编译器套件是否匹配。如果你装的是 QT 5.15.2 MSVC2019 64bit直接打开 ordersystem.pro 基本不会有大问题。但如果你用的是 QT 6.x要注意几个点QRegExp 在 QT 6 里被移到了兼容模块QTextCodec 也变了位置如果源码里用了这些编译会报错。稳妥的做法是装一个 QT 5.15.x 的长期支持版本和工程年代对齐。MySQL 驱动是另一个关键。QT 默认不带 MySQL 驱动你需要确认 QT 安装目录下的 plugins/sqldrivers 里有没有 qsqlmysql.dll。如果没有就得自己编译驱动或者直接用已经编译好的版本。常见做法是先确认 MySQL 的版本然后找对应版本的驱动文件放进 sqldrivers 目录。提示QT 5.15.2 的离线安装包在 QT 官网归档里还能找到安装时记得勾选 Sources 和对应的编译器套件不然后面编译驱动会缺头文件。2.2 数据库建库与连接配置工程里 connection.h 是数据库连接的核心文件。打开它你会看到类似 QSqlDatabase::addDatabase(QMYSQL) 的调用后面跟着 setHostName、setDatabaseName、setUserName、setPassword 这些配置。你需要根据自己本地的 MySQL 环境改这几个参数。先建库。打开 MySQL 命令行或者 Navicat执行CREATE DATABASE order_room DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;然后建表。工程里没有附带 .sql 建表文件这是这份资源的一个小坑。你需要根据代码里的 SQL 语句反推表结构。我一般会先搜代码里所有QSqlQuery的exec调用把 CREATE TABLE 或者 INSERT 语句找出来。常见的表有这么几张表名用途关键字段user统一用户表id, username, password, roleroom机房信息room_id, room_name, capacity, statusorder_info预约记录order_id, user_id, room_id, order_date, time_slot, statusnotice公告notice_id, content, publish_time字段类型根据代码里的绑定值来定。比如bindValue(:username, username)传的是 QString数据库里就用 VARCHAR。日期用 DATE 或 DATETIME状态用 INT 或 VARCHAR 都行看代码里怎么比较的。改完 connection.h 之后编译运行。如果登录窗口能弹出来说明数据库连接通了。如果弹不出来或者点了登录没反应先看 QT Creator 的 Application Output 里有没有QSqlError的报错信息。// connection.h 里典型的连接代码 QSqlDatabase db QSqlDatabase::addDatabase(QMYSQL); db.setHostName(127.0.0.1); // 本机就写 localhost 或 127.0.0.1 db.setPort(3306); // MySQL 默认端口 db.setDatabaseName(order_room); db.setUserName(root); db.setPassword(your_password); // 改成你自己的密码 if (!db.open()) { qDebug() 连接失败 db.lastError().text(); }这段代码的逻辑很直白注册 QMYSQL 驱动设置连接参数尝试打开。lastError().text()是排错的关键它会告诉你到底是驱动没加载、密码错了、还是库不存在。参数方面setHostName如果 MySQL 和 QT 在同一台机器上写127.0.0.1比写localhost更稳因为localhost在某些配置下会走 socket 而不是 TCP。2.3 编译报错的高频位置第一次编译大概率会碰到几类错误。一类是cannot find -lqsqlmysql说明驱动没配好。另一类是dependent ..\..\..\..\..\..\qt\5.15.2\msvc2019_64\include\qtwid does not exist这种路径报错通常是因为 .pro 文件里写了绝对路径或者 .qmake.stash 缓存了旧路径。解决办法是删掉 .qmake.stash 和 Makefile重新执行 qmake。还有一类是中文乱码。QT 5 默认用 UTF-8但 MSVC 编译器有时候会把源码当成 GBK。在 .pro 里加一行QMAKE_CXXFLAGS /utf-8这行只对 MSVC 有效。如果你用 MinGW一般不需要加但可以在 main.cpp 里设置QTextCodec::setCodecForLocale(QTextCodec::codecForName(UTF-8))来统一编码。3. 角色权限与预约逻辑三套 UI 背后的数据流3.1 登录分流与角色判定login.cpp 是整个系统的入口。它做的事情不复杂拿用户输入的账号密码去 user 表里查查到之后根据 role 字段决定跳转到哪个窗口。学生进 student.ui教师进 teacher.ui管理员进 manager.ui。代码结构大概是这样的// login.cpp 里的登录校验逻辑 QSqlQuery query; query.prepare(SELECT id, role FROM user WHERE username :user AND password :pwd); query.bindValue(:user, ui-lineEdit_user-text()); query.bindValue(:pwd, ui-lineEdit_pwd-text()); if (query.exec() query.next()) { int role query.value(role).toInt(); int uid query.value(id).toInt(); if (role 0) { StudentWindow *w new StudentWindow(uid); w-show(); } else if (role 1) { TeacherWindow *w new TeacherWindow(uid); w-show(); } else { ManagerWindow *w new ManagerWindow(); w-show(); } this-close(); } else { QMessageBox::warning(this, 登录失败, 账号或密码错误); }preparebindValue是防 SQL 注入的标准写法比直接拼字符串安全。query.next()判断有没有查到记录查到就取 role 和 id。id 传给子窗口子窗口后续查预约记录、查个人信息都要用这个 id 做过滤条件。role 的取值 0、1、2 分别对应学生、教师、管理员这个映射关系在代码里是硬编码的改的时候要三处一起改。3.2 学生端预约流程与时间冲突检测学生端的核心功能是查机房、选时间段、提交预约。student.cpp 里会有查询可用机房的逻辑一般是查 room 表里 status 为可用的记录然后按容量或者位置排序。预约提交的时候最关键的是冲突检测。同一个机房、同一个时间段不能有两条有效预约。代码里通常会先查 order_info 表// 预约冲突检测 QSqlQuery check; check.prepare(SELECT COUNT(*) FROM order_info WHERE room_id :rid AND order_date :date AND time_slot :slot AND status 1); check.bindValue(:rid, roomId); check.bindValue(:date, date.toString(yyyy-MM-dd)); check.bindValue(:slot, timeSlot); check.exec(); check.next(); if (check.value(0).toInt() 0) { QMessageBox::information(this, 提示, 该时间段已被预约); return; }status 1表示预约有效取消的预约 status 改成 0这样历史记录还在但不会影响冲突判断。time_slot字段存的是时间段编号比如 1 表示上午、2 表示下午、3 表示晚上具体怎么分看代码里的定义。日期用yyyy-MM-dd格式存成字符串或者 DATE 类型都行但比较的时候格式要一致。注意如果数据库里 order_date 存的是 DATETIME而代码里传的是 DATE 字符串MySQL 会自动转换但索引可能失效。数据量大的时候建议统一用 DATE 类型。3.3 教师端与管理员端的差异教师端的权限比学生多一层可以查看自己名下所有学生的预约情况也可以替学生代预约。teacher.cpp 里会有按教师 id 查关联学生的逻辑通常是通过班级或者课程表来关联。如果工程里没有班级表那教师端可能只是简单地查看全部预约记录然后按教师自己的课程做筛选。管理员端的 manager.cpp 功能最全增删改查机房、审核预约、发布公告、管理用户。manager.ui 里的控件也最多表格、按钮、输入框一大堆。管理员的预约审核逻辑一般是把 order_info 的 status 从待审核改成已通过或者已拒绝。如果代码里没有审核状态字段那预约就是提交即生效管理员只能做删除操作。三套 UI 的 .ui 文件都是 QT Designer 生成的 XML用 QT Creator 打开就能可视化编辑。如果你想改界面布局直接双击 .ui 文件拖控件就行改完保存重新编译ui_.h 会自动更新。但要注意如果你手动改了 ui_.h重新编译时会被覆盖所以所有界面改动都应该在 .ui 文件里做。4. 避坑与排查编译、连接、乱码、崩溃的常见问题4.1 驱动加载失败QMYSQL driver not loaded现象程序启动后数据库连接返回 falseApplication Output 里打印QSqlDatabase: QMYSQL driver not loaded。原因QT 的 sqldrivers 目录下没有 qsqlmysql.dll或者 dll 的位数和 QT 套件不匹配32 位 vs 64 位或者 MySQL 的 libmysql.dll 不在 PATH 里。解决先确认 QT 安装目录下plugins/sqldrivers里有没有 qsqlmysql.dll。如果没有去 QT 安装目录的Sources/qtbase/src/plugins/sqldrivers/mysql下编译或者直接下载对应版本的预编译驱动。然后把 MySQL 安装目录下的 libmysql.dll 复制到 QT 的 bin 目录或者工程输出目录。最后在代码里加qDebug() QSqlDatabase::drivers();看看 QMYSQL 在不在列表里。4.2 中文乱码界面显示问号或方块现象界面上的中文标签、按钮文字显示成问号或者方块。原因源码文件编码、编译器编码、QT 运行时编码三者不一致。MSVC 默认用 GBK 读源码而 QT 5 默认用 UTF-8 处理字符串。解决在 .pro 里加QMAKE_CXXFLAGS /utf-8强制 MSVC 用 UTF-8 读源码。如果还有问题在 main.cpp 里加QTextCodec::setCodecForLocale(QTextCodec::codecForName(UTF-8))。另外检查 .ui 文件里的中文是不是 UTF-8 编码用 Notepad 或者 VS Code 转一下编码。4.3 编译报错dependent ............\qt\5.15.2\msvc2019_64\include\qtwid does not exist现象qmake 或者编译的时候报路径不存在路径里有一长串..。原因.qmake.stash 或者 Makefile 里缓存了旧的 QT 安装路径你换了 QT 版本或者挪了工程目录之后缓存没清。解决删掉工程目录下的 .qmake.stash、Makefile、Makefile.Debug、Makefile.Release然后在 QT Creator 里执行「构建」→「执行 qmake」再重新编译。如果还不行检查 .pro 文件里有没有写死的 INCLUDEPATH 或者 LIBS 路径改成相对路径或者用$$[QT_INSTALL_HEADERS]这种变量。4.4 程序崩溃点击按钮后闪退现象登录成功但点击某个功能按钮后程序直接退出没有报错弹窗。原因空指针访问、数组越界、或者数据库查询返回空结果时没有做判空。解决在 QT Creator 里用 Debug 模式运行崩溃时看调用栈。常见的位置是query.value(0)在query.next()返回 false 的时候被调用或者ui-tableWidget-item(row, col)在 item 为空的时候被访问。给所有query.next()加判断给所有item()加判空能解决大部分闪退。4.5 预约时间冲突没拦住同一时段出现两条记录现象两个学生同时预约同一个机房的同一时段系统都提示成功。原因冲突检测和插入之间有时间窗口并发情况下两个请求都通过了检测。解决在 order_info 表的(room_id, order_date, time_slot, status)上建唯一索引或者在插入的时候用INSERT ... SELECT ... WHERE NOT EXISTS的写法。课设级别一般不会真的并发但如果你要演示给老师看加个唯一索引更稳妥。ALTER TABLE order_info ADD UNIQUE KEY uk_room_time (room_id, order_date, time_slot, status);5. 从能跑到好用几个让课设加分的小改动5.1 给预约表加一个状态字段和审核流程原工程如果只是提交即生效你可以加一个 status 字段0 表示待审核1 表示已通过2 表示已拒绝。管理员端加一个审核按钮教师端加一个查看待审核列表的功能。这样整个系统就从「增删改查」升级成了「带工作流的业务系统」答辩的时候有的讲。改动点集中在三处order_info 表加字段、学生端提交时默认 status0、管理员端加审核按钮和对应的 UPDATE 语句。代码量不大但业务完整度提升明显。5.2 用 QSS 统一界面风格QT 默认的界面控件风格比较朴素。你可以在 main.cpp 里加载一个 .qss 文件统一按钮、表格、输入框的样式。比如QPushButton { background-color: #4a90d9; color: white; border-radius: 4px; padding: 6px 16px; } QLineEdit { border: 1px solid #ccc; border-radius: 4px; padding: 4px; }把这段存成 style.qss在 main.cpp 里用QFile读进来qApp-setStyleSheet(content)。界面立刻从「课设风」变成「产品风」老师一看就觉得你花了心思。5.3 加一个日志模块方便排查问题工程里有一个 orderInfo.log 文件说明原作者已经有日志意识了。你可以把它扩展成一个简单的日志类在关键操作处写日志登录、预约、取消、审核。日志格式带上时间戳和用户 id出问题的时候直接看日志文件比在代码里到处加 qDebug 高效得多。void writeLog(const QString action, int userId) { QFile file(orderInfo.log); if (file.open(QIODevice::Append | QIODevice::Text)) { QTextStream out(file); out QDateTime::currentDateTime().toString(yyyy-MM-dd hh:mm:ss) | user: userId | action \n; file.close(); } }这个函数放在 global.cpp 里哪里需要就调一下。参数 action 写具体操作userId 写当前登录用户的 id。日志文件会越来越大课设级别不用管滚动切割但你可以加一个按日期分文件的小逻辑显得更专业。5.4 数据库连接用单例别每次操作都新建connection.h 如果每次查询都addDatabase会重复注册连接QT 会警告duplicate connection name。正确的做法是用单例模式全局只初始化一次后面所有查询复用同一个QSqlDatabase对象。改法很简单把连接逻辑放到一个静态函数里第一次调用时初始化后面直接返回已有的连接。QSqlDatabase getDb() { static QSqlDatabase db; if (!db.isValid()) { db QSqlDatabase::addDatabase(QMYSQL); db.setHostName(127.0.0.1); // ... 其他配置 db.open(); } return db; }这样改完连接只建一次查询效率更高也不会再报重复连接的警告。参数方面static保证了只初始化一次isValid()判断是否已经配置过。如果你需要多线程访问数据库每个线程要单独建连接那就不能用这个单例得改成按线程存储。5.5 打包发布让没装 QT 的电脑也能跑课设答辩的时候老师的电脑不一定有 QT 环境。你需要用windeployqt工具把依赖的 dll 打包到一起。步骤是先用 Release 模式编译然后把生成的 exe 复制到一个空文件夹在 QT 命令行里执行windeployqt your.exe它会自动把 Qt5Core.dll、Qt5Gui.dll、Qt5Sql.dll、platforms/qwindows.dll 这些复制过来。MySQL 的 libmysql.dll 和 sqldrivers/qsqlmysql.dll 要手动复制。最后把整个文件夹压缩到任何 Windows 电脑上解压就能跑。从那以后我每次交付 QT 项目都会先在干净虚拟机上跑一遍 windeployqt 打包确认没有缺 dll 再交出去。这个习惯帮我省掉了无数次「在我电脑上好好的」的尴尬。希望帮到你。本文还有配套的精品资源点击获取