
简介本资源为基于Qt与MySQL的医院预约管理系统完整项目包面向计算机相关专业的在校学生、教师及企业开发者可用于毕业设计、课程设计、作业提交或项目初期立项演示。项目已通过导师指导与答辩评审获得95分高分代码经过测试运行功能完整可靠。压缩包共47个文件约31KB包含15个cpp源文件、15个h头文件、12个ui界面文件以及pro工程文件、user配置、README说明和授权码文本等覆盖登录、注册、挂号、选科室、选时间、医生与管理员管理等模块目录结构清晰。已有62人学习关注。读者可获得完整可运行的源码、数据库管理逻辑、界面设计文件与项目文档既能直接用于毕设课设也可在此基础上修改扩展新功能适合Qt与MySQL入门进阶学习。1. 从一份 QtMysql 门诊预约源码说起它到底能跑通什么如果你正在找一套能直接跑起来的 C 桌面端项目又恰好被 Qt 的信号槽和 MySQL 的连接配置折腾过那这份基于 QtMysql 的医院预约管理系统源码包值得先看一眼。它不是那种只丢几个 cpp 文件让你自己拼的“半成品”而是把登录、注册、科室选择、时间选择、医生排班、患者挂号、管理员后台这些门诊流程里最核心的环节都做成了可编译的工程。整个项目用 qmake 组织.pro文件里把 Qt 的模块依赖写得比较清楚数据库层单独抽了databasemanager来管连接和查询界面用.ui文件配合手写逻辑属于典型的课程设计/毕设级桌面应用结构。适合谁计算机相关专业做课设、毕设的学生或者想拿一个完整 Qt 项目练手信号槽、多窗口跳转、数据库增删改查的开发者。它解决的不是“高并发挂号”这种生产级问题而是“怎么把一套带图形界面、带数据库持久化、带角色权限的桌面系统从零搭出来”的教学级需求。源码包里除了代码还有详细文档和授权说明对照着复现的人比较友好。下面我按实际拆包和编译的顺序把这份资源从环境到跑通、再到改功能的路子捋一遍。2. 环境搭不起来后面全是白搭Qt 版本、MySQL 驱动与 .pro 配置2.1 为什么 Qt 版本和编译器组合要先定死这份工程用的是 qmake 构建.pro文件里没有写死 Qt 的具体小版本但实际编译时 Qt 5 和 Qt 6 的差异会直接导致报错。常见做法是优先用 Qt 5.14 或 Qt 5.15 配 MinGW 编译器因为工程里的.ui文件和QSqlDatabase相关调用在 Qt 5 下最稳。如果你用 Qt 6QTextCodec这类头文件可能已经移除而老项目里经常顺手就 include 了。另一个坑是编译器位数MySQL 的 C 连接库分 32 位和 64 位Qt 的 MinGW 也分 32/64两边必须一致否则编译能过、运行时报“driver not loaded”。我一般会先确认三件事Qt Creator 的 Kit 里编译器是 MinGW 64-bit 还是 32-bitMySQL 安装的是哪个版本libmysql.dll和libmysqld.dll放在哪个目录。这三者对齐了后面才谈得上连数据库。2.2 把 MySQL 驱动塞进 Qt 的正确姿势Qt 默认不带 MySQL 驱动需要自己编译或找现成的qsqlmysql.dll。源码包里通常不会附带这个驱动所以这是第一个要自己补的环节。步骤不复杂但顺序错了就会一直报QMYSQL driver not loaded。# 先确认 Qt 安装目录下的 sqldrivers 文件夹里有没有 qsqlmysql.dll # 常见路径以 MinGW 64-bit 为例 # C:\Qt\5.15.2\mingw81_64\plugins\sqldrivers\ # 如果没有需要自己编译 Qt 的 MySQL 驱动插件 # 进入 Qt 源码的 sqldrivers/mysql 目录用 qmake 生成 Makefile cd C:\Qt\5.15.2\Src\qtbase\src\plugins\sqldrivers\mysql qmake -- MYSQL_INCDIRC:/Program Files/MySQL/MySQL Server 8.0/include ^ MYSQL_LIBDIRC:/Program Files/MySQL/MySQL Server 8.0/lib mingw32-make mingw32-make install这段命令的核心是告诉 qmake 两件事MySQL 头文件在哪、库文件在哪。MYSQL_INCDIR指向mysql.h所在目录MYSQL_LIBDIR指向libmysql.lib所在目录。编译完成后qsqlmysql.dll会被安装到 Qt 的plugins/sqldrivers下。注意光有 dll 还不够运行时libmysql.dll必须能被找到通常把它复制到可执行文件同目录或者加到系统 PATH 里。提示如果你用的是 MySQL 8.0认证插件默认是caching_sha2_password而老版 Qt 驱动可能只认mysql_native_password。连不上时先改用户认证方式别急着怀疑代码。2.3 .pro 文件里必须检查的几行打开outpatients-appointment-system.pro重点看QT 这一行有没有包含sql。如果只有core gui widgets那QSqlDatabase相关类根本链接不进来。另外TARGET和TEMPLATE决定了生成的可执行文件名和工程类型一般不用动。SOURCES和HEADERS里列出的文件如果和实际目录对不上编译会直接报找不到文件这时候要么改路径要么把文件挪到对应位置。QT core gui sql greaterThan(QT_MAJOR_VERSION, 4): QT widgets TARGET outpatients-appointment-system TEMPLATE app这三行是工程能编译和连库的基础。sql模块负责数据库连接widgets负责界面控件。如果编译时报undefined reference to QSqlDatabase::...九成是这里漏了sql。3. 从登录到挂号核心模块的代码走读与数据库表对应关系3.1 登录与注册信号槽怎么把界面和数据库串起来login.cpp和register.cpp是入口逻辑。登录界面收集用户名和密码后通过databasemanager去查数据库匹配成功就跳转到主窗口。这里的关键不是界面长什么样而是信号槽的连接方式按钮的clicked()信号连到自定义槽函数槽函数里再调数据库查询。这种写法在 Qt 里很标准但新手容易在“查询结果怎么传回界面”这一步卡住。// login.cpp 里典型的登录校验逻辑 void Login::on_loginButton_clicked() { QString username ui-usernameEdit-text().trimmed(); QString password ui-passwordEdit-text().trimmed(); // 通过 DatabaseManager 单例查询用户表 QSqlQuery query; query.prepare(SELECT role FROM user WHERE username ? AND password ?); query.addBindValue(username); query.addBindValue(password); if (query.exec() query.next()) { QString role query.value(role).toString(); // 根据角色跳转到不同窗口 if (role admin) { adminWindow new Administrator(); adminWindow-show(); } else { mainWindow new MainWindow(); mainWindow-show(); } this-close(); } else { QMessageBox::warning(this, 登录失败, 用户名或密码错误); } }这段代码里prepare加addBindValue是防 SQL 注入的标准写法比直接拼字符串安全。query.next()判断有没有查到记录查到就取role字段决定跳转目标。参数说明usernameEdit和passwordEdit是.ui文件里定义的控件对象名如果你改了界面控件的 objectName这里也要同步改否则编译能过但运行时空指针。3.2 科室与时间选择多窗口跳转的数据传递choosedepartment.cpp和choosetime.cpp负责让患者选科室和就诊时间。这两个模块的难点不在界面而在窗口之间怎么传数据。常见做法是用构造函数传参或者用全局变量。这份工程里我看到的做法是选择科室后把科室 ID 存到一个成员变量再打开时间选择窗口时带过去。// choosedepartment.cpp 里选中科室后打开时间选择窗口 void ChooseDepartment::on_departmentList_itemClicked(QListWidgetItem *item) { // 从 item 的 data 里取出科室 ID int deptId item-data(Qt::UserRole).toInt(); QString deptName item-text(); // 把科室信息传给时间选择窗口 ChooseTime *timeWindow new ChooseTime(deptId, deptName); timeWindow-show(); this-hide(); }这里Qt::UserRole是 Qt 预留的自定义数据角色用来存数据库里的科室 ID界面上只显示科室名称。这样既不影响用户看又能把 ID 带进下一步。ChooseTime的构造函数接收两个参数在它内部再根据科室 ID 查该科室下有哪些医生、哪些时间段可约。如果你要改成“先选医生再选时间”改这里的跳转顺序和查询条件就行。3.3 数据库表结构至少要有哪几张表虽然源码包里没有单独的.sql建表文件但从代码里的查询语句可以反推出核心表结构。常见做法是至少建四张表用户表、科室表、医生表、预约记录表。下面这张表是我根据代码逻辑整理的字段对应关系实际建表时字段名要和代码里的 SQL 保持一致。表名关键字段用途代码中对应查询userid, username, password, role登录与角色判断login.cpp 登录校验departmentid, name科室列表展示choosedepartment.cpp 查询doctorid, name, dept_id, schedule医生信息与排班choosetime.cpp 按科室查医生appointmentid, patient_id, doctor_id, time, status预约记录tiingzhen.cpp 挂号写入建表时注意role字段用字符串存admin和patient代码里就是按字符串比较的。appointment表的status可以存booked、cancelled这类状态方便后续做取消预约功能。如果你要加“科室简介”或“医生职称”在对应表里加字段然后在界面代码里多取一个值就行。4. 编译通过只是开始运行期连库失败与界面卡死的排查4.1 连库失败的三种典型现象与定位方法第一种现象程序启动就弹窗说QMYSQL driver not loaded。这说明 Qt 根本没找到 MySQL 驱动插件去 Qt 安装目录的plugins/sqldrivers下看有没有qsqlmysql.dll没有就按第 2 章的步骤编译。第二种现象驱动加载了但QSqlDatabase::open()返回 false。这时候用db.lastError().text()把错误打出来常见的是用户名密码错、主机地址不对、或者 MySQL 服务没启动。第三种现象编译时链接报错undefined reference to mysql_init说明.pro里没有链接 MySQL 的库需要在LIBS里加上-lmysql。// 在 databasemanager.cpp 里加错误输出方便定位 QSqlDatabase db QSqlDatabase::addDatabase(QMYSQL); db.setHostName(127.0.0.1); db.setPort(3306); db.setDatabaseName(hospital_db); db.setUserName(root); db.setPassword(your_password); if (!db.open()) { qDebug() 数据库连接失败: db.lastError().text(); return false; }qDebug()输出的错误信息会出现在 Qt Creator 的应用程序输出窗口里比弹窗更详细。setHostName用127.0.0.1比localhost更稳因为某些环境下localhost会走 socket 而不是 TCP。setPort默认 3306如果你装 MySQL 时改过端口这里要同步改。4.2 界面卡死与中文乱码两个高频翻车点界面卡死通常发生在数据库查询耗时较长时主线程被阻塞窗口就无响应了。这份工程里的查询都是同步的数据量小的时候感觉不到一旦预约记录多了就会卡。常见做法是把查询放到QThread里或者至少加个QApplication::processEvents()让界面喘口气。不过对于课设级项目数据量不大先保证功能跑通更重要。中文乱码分两种一种是数据库里存进去就是乱码另一种是界面显示乱码。前者检查 MySQL 的字符集是不是utf8mb4建库建表时指定CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci。后者检查 Qt 源文件编码Qt Creator 里默认是 UTF-8但如果你的系统是 GBK.ui文件里的中文可能显示不正常。在main.cpp里加QTextCodec::setCodecForLocale(QTextCodec::codecForName(UTF-8))可以统一编码但 Qt 6 里这个类没了所以还是建议从建库阶段就统一用 UTF-8。注意改完数据库字符集后已经存进去的乱码数据不会自动恢复需要重新录入或者用 SQL 更新。5. 避坑清单从拆包到答辩这五个坑我替你踩过了5.1 坑一.pro.user文件直接打开导致 Kit 错乱现象用 Qt Creator 打开工程后编译按钮是灰的或者提示“没有可用的 Kit”。原因源码包里带了outpatients-appointment-system.pro.user这个文件记录了原作者的 Qt 路径和编译器配置到你机器上路径对不上就失效了。解决删掉.pro.user文件重新用 Qt Creator 打开.pro让它根据你本地的环境重新生成配置。这一步几乎每次换机器都要做别嫌麻烦。5.2 坑二数据库名和代码里写的不一致现象编译通过运行后登录报“用户名或密码错误”但数据库里明明有数据。原因代码里setDatabaseName(hospital_db)写的是某个库名而你本地建的库叫别的名字或者根本没建库。解决全局搜索代码里的数据库名统一改成你本地实际的库名同时确认表名和字段名也和代码里的 SQL 一致。常见做法是先把代码里的 SQL 语句复制到 MySQL 客户端里执行一遍能查到结果再跑程序。5.3 坑三MySQL 8.0 认证插件不兼容现象QSqlDatabase::open()返回 false错误信息里带Authentication plugin caching_sha2_password cannot be loaded。原因MySQL 8.0 默认用caching_sha2_password而老版 Qt 的 MySQL 驱动只支持mysql_native_password。解决改用户认证方式执行ALTER USER rootlocalhost IDENTIFIED WITH mysql_native_password BY 你的密码;然后FLUSH PRIVILEGES;。改完再连基本就能通。5.4 坑四界面控件 objectName 被改后代码找不到现象程序启动后某个按钮点了没反应或者直接崩溃。原因你在 Qt Designer 里改了控件的 objectName但对应的.cpp里还在用旧名字调ui-oldName。解决改完.ui后全局搜索旧 objectName把所有引用同步改掉。更稳妥的做法是改之前先记下哪些控件在代码里被引用过只改没被引用的或者改完立刻编译看报错。5.5 坑五预约时间没有做冲突校验现象同一个医生同一时间段被多个患者预约成功数据库里出现重复记录。原因tiingzhen.cpp里写入预约记录前没有查重直接 insert。解决在插入前先SELECT COUNT(*) FROM appointment WHERE doctor_id ? AND time ?如果大于 0 就提示“该时段已被预约”。这个校验加在业务层比加在数据库唯一索引更灵活因为你可以给用户更友好的提示。6. 在现有代码上加功能从“能跑”到“能改”的进阶手法6.1 加一个“取消预约”功能需要动哪几个文件取消预约的本质是把appointment表里某条记录的status从booked改成cancelled或者在界面上直接删除记录。我一般会先在患者主窗口加一个“我的预约”列表用QTableWidget展示当前患者的预约记录每行加一个“取消”按钮。按钮的槽函数里拿到预约 ID执行 UPDATE 语句。// 在 patient.cpp 里加取消预约的槽函数 void Patient::on_cancelButton_clicked() { int row ui-appointmentTable-currentRow(); if (row 0) { QMessageBox::information(this, 提示, 请先选中一条预约记录); return; } int appointmentId ui-appointmentTable-item(row, 0)-text().toInt(); QSqlQuery query; query.prepare(UPDATE appointment SET status cancelled WHERE id ?); query.addBindValue(appointmentId); if (query.exec()) { QMessageBox::information(this, 成功, 预约已取消); refreshAppointmentTable(); // 刷新列表 } else { QMessageBox::warning(this, 失败, 取消失败请重试); } }这里currentRow()拿到用户选中的行号再从第一列取预约 ID。refreshAppointmentTable()是你自己写的刷新函数重新查一遍数据库把最新状态显示出来。参数说明appointmentTable是QTableWidget的 objectName第一列存的是预约 ID这个列可以隐藏起来不显示给用户但数据要存进去。6.2 用 QSS 快速改界面风格不用动 .ui 文件如果你觉得默认的灰色界面太“课设风”可以用 QSS 给控件换颜色和圆角。在main.cpp里读一个.qss文件或者直接在代码里写样式字符串。常见做法是给按钮加圆角和悬停变色给输入框加边框。// 在 main.cpp 里加载 QSS 样式 QFile styleFile(:/style.qss); if (styleFile.open(QFile::ReadOnly)) { QString style QLatin1String(styleFile.readAll()); qApp-setStyleSheet(style); }对应的style.qss内容示例QPushButton { background-color: #4a90d9; color: white; border-radius: 4px; padding: 6px 16px; } QPushButton:hover { background-color: #357abd; } QLineEdit { border: 1px solid #ccc; border-radius: 3px; padding: 4px; }QSS 的好处是不用改.ui文件也不影响逻辑代码改完重新运行就能看到效果。注意资源文件路径如果 QSS 放在qrc资源里用:/style.qss如果放在可执行文件旁边用相对路径style.qss。6.3 答辩前必做的三项验证第一项把数据库导出成.sql文件换一台机器导入后重新编译运行确认不依赖你本地的特殊配置。第二项把所有窗口的跳转路径走一遍特别是登录失败、注册重复用户名、预约时间冲突这些异常分支确保不会崩溃。第三项检查代码里有没有硬编码的绝对路径比如C:/Users/xxx/...有的话改成相对路径或资源路径。从那以后我每次拿到别人的 Qt 工程都强制先删.pro.user、再对数据库名、最后跑一遍全流程异常分支这三步走完基本不会在演示时翻车。希望帮到你。本文还有配套的精品资源点击获取