这次我们来看一个非常经典的 Qt 入门实战项目C 配合 Qt6 框架 MySQL 数据库做一套完整的桌面应用。这个方向特别适合刚学完 C 语法、想接触 GUI 开发和数据库操作的编程小白。文章会直接告诉你这套技术栈要准备什么环境、怎么建项目、怎么写增删改查、会遇到哪些高频问题以及如何把它打包成可以发给别人的 exe。先看核心信息这不是一个需要高端显卡、复杂编译参数的项目而是用 Qt Creator 可视化拖控件 写 C 逻辑 用 MySQL 存数据。只要你的电脑能跑 Visual Studio 或者 Qt Creator硬盘剩余空间 20G 左右普通 8G 内存的机器就能很舒服地开发。数据库用 MySQL 8.0 社区版Qt 用 6.5 以上版本IDE 用 Qt Creator。这篇文章我会带你完成五件事装好 Qt 6 和 MySQL设计一个最少但完整的数据库表用 Qt Widgets 搭建主界面实现连接数据库、查询、插入、修改、删除最后做一次打包发布和坑点排查。文章里所有代码都是可以直接复制到项目里跑的不绕弯子。1. 核心能力速览能力项说明技术栈C17 / C20Qt6 WidgetsQt SQL 模块MySQL 8.0适合人群有 C 基础语法知识的初学者想完成第一个带界面的数据库项目开发平台Windows 10/11 为主同样支持 Linux/macOS硬件要求普通 x64 CPU8G 内存即可不需要独立显卡核心功能数据库连接、登录校验、表格展示、增删改查、按关键词查询启动方式Qt Creator 打开项目后直接构建运行是否支持一键打包支持使用 windeployqt 生成可发布的 exe 目录数据库需求本机安装 MySQL 服务监听 3306 端口学习收益掌握 Qt 信号槽、常用控件、Model/View 架构、QSqlQuery、QSqlTableModel这个项目的最大价值不是“看起来很酷”而是把 C、GUI、SQL 三样东西串起来让你知道一个真实软件大概是怎么组织的。这不是玩具项目它足够撑起课程设计也足够作为简历里的第一个完整项目。2. 适用场景与学习边界2.1 这个项目适合谁刚学完 C 的类、指针、文件读写但不知道这些能干什么的初学者。想从控制台程序进阶到窗口程序但直接看 Qt 源码又觉得信息量太大的学习者。准备做课程设计、毕业设计需要一套“界面 数据库 完整业务”模板的同学。已经在用 C 写后台服务想补一下图形界面开发能力的后端开发。2.2 能解决的问题完成这个项目后你会理解Qt 项目的基本目录结构.pro或CMakeLists.txt、头文件、源文件、界面文件。信号槽机制是什么为什么按钮点击能关联到一段 C 函数。Qt 的 Model/View 架构如何用 QSqlTableModel 把数据库表直接映射到表格控件。SQL 的增删改查如何和界面按钮绑定。如何通过 QSqlDatabase 管理 MySQL 连接如何排查驱动加载失败。2.3 不适合什么场景如果你连 C 最基本的类、函数重载、vector 还没搞明白建议先刷一遍基础语法再回来。如果你要做高并发、分布式、服务器后端这个项目不是你要的答案请去看数据库中间件和网络编程。如果你想做马化腾级别的客户端项目这个项目只是起点不要抱着一步到位的心态。2.4 版权与安全边界本项目采用 Qt 开源协议使用 LGPLv3 许可证。个人学习、开源项目完全没问题如果你要闭源商业分发请遵循 Qt 的许可证要求或者购买商业授权。MySQL 使用社区版时也要注意其开源协议。项目里不要保存真实用户的明文密码学习阶段可以用明文演示真实工程中应使用哈希加盐存储。3. 环境准备与前置条件3.1 操作系统与软件清单开发这个项目你需要准备软件推荐版本说明Windows 10/1164 位其他平台类似但驱动安装方式略有差异Qt6.5 及以上安装时勾选 Qt Widgets、Qt SQL、Qt 网络模块Qt Creator随 Qt 安装包附带也可以用 Visual Studio 插件MySQL8.0 社区版也可以用 MariaDB但连接驱动名一样MySQL 客户端工具MySQL Workbench 或 Navicat用于建库建表和查看数据C 编译器MSVC 2022 或 MinGW 11.2安装 Qt 时选择对应套件注意一个最常见的坑如果你在安装 Qt 时没有勾选对应的编译器套件Qt Creator 会提示“No suitable kits found”这是小白第一次遇到 Qt 最容易卡住的地方。Qt 安装器里需要同时勾选Qt 6.x 下的Qt Multi Media可选本项目不需要。必须勾选Qt 6.x下的Qt Widgets。必须勾选Qt 6.x下的Additional Libraries里的Qt SQL。如果你用 MinGW那么装哪一版编译器就要选对应的 MinGW kit如果你用 MSVC先装好 Visual Studio 2022 Build Tools。3.2 C 基础自查你需要具备这些 C 能力缺哪个补哪个能写类能理解构造函数、私有成员、公有方法。知道指针和引用的区别知道nullptr。能使用QString和std::string的基本转换。能看懂lambda表达式因为 Qt 信号槽经常用 lambda 简化代码。能处理 include 头文件和命名空间的基础问题。不需要深入模板元编程不需要多线程不需要网络编程。这个项目只涉及单线程数据库操作把基础语法练好就行。4. 安装部署与数据库初始化4.1 Qt 安装要点到 Qt 官网下载 Qt Online Installer登录账号后选择自定义安装。注意安装路径不要带中文和空格推荐安装到D:\Qt。安装时勾选Qt 6.5.3 ├── MinGW 11.2.0 64-bit └── Qt 5 Compatibility Module (可选)如果你的开发环境是 Visual Studio那么请先安装 VS2022 C 桌面开发组件在 Qt 安装器里选MSVC 2019 64-bit或MSVC 2022 64-bit套件。安装完成后打开 Qt Creator在“工具 → 选项 → Kits”里能看到自动识别出来的套件。这一步最容易出现的问题安装时没有勾选 SQL 模块后面找不到#include QSqlDatabase。编译器套件缺失界面显示红色错误。建议安装完成之后先在 Qt Creator 里新建一个空的 Widgets Application编译运行一次确认环境没问题再继续往下做。4.2 MySQL 安装与建库MySQL 可以直接去官网下载 MySQL Community Server 8.0 安装包。安装时选择 Developer Default 或者只装 Server 和 Workbench。配置 root 密码时记住它后面 Qt 连接数据库要用。安装完成后打开 MySQL Command Line Client 或者 MySQL Workbench执行下面的 SQLCREATE DATABASE IF NOT EXISTS student_db DEFAULT CHARACTER SET utf8mb4; USE student_db; CREATE TABLE IF NOT EXISTS student ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(50) NOT NULL, age INT NOT NULL, major VARCHAR(100), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); INSERT INTO student(name, age, major) VALUES (张三, 20, 计算机科学与技术), (李四, 21, 软件工程), (王五, 22, 数据科学);这里就是把数据库设置为 utf8mb4避免中文乱码。建完表后执行SELECT * FROM student;能看到三条数据说明 MySQL 正常。这里还要注意一个 Qt 6 连接 MySQL 8 的高频问题。MySQL 8 默认使用caching_sha2_password认证插件而 Qt 自带的 MySQL 驱动在某些版本上可能不支持。为了让学习过程更顺畅可以创建一个使用旧认证方式的用户CREATE USER qtuserlocalhost IDENTIFIED WITH mysql_native_password BY 123456; GRANT ALL PRIVILEGES ON student_db.* TO qtuserlocalhost; FLUSH PRIVILEGES;然后在 Qt 程序里就用qtuser连接避免认证插件问题。如果你的 Qt 版本已经支持新认证方式这一步可以跳过。5. Qt 项目创建与工程配置5.1 创建项目打开 Qt Creator点击“文件 → 新建项目 → Application → Qt Widgets Application”项目名写StudentSystem构建系统选CMake。注意类名和文件名不要带中文路径不要有空格。创建时勾选Qt CoreQt GUIQt WidgetsQt SQL正常创建后Qt Creator 会生成以下文件StudentSystem/ ├── CMakeLists.txt ├── main.cpp ├── MainWindow.h ├── MainWindow.cpp └── MainWindow.ui5.2 修改 CMakeLists.txtQt 6 默认使用 CMake这是推荐的方式。打开CMakeLists.txt确保里面包含了 Sql 模块cmake_minimum_required(VERSION 3.16) project(StudentSystem VERSION 0.1 LANGUAGES CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) set(CMAKE_AUTOUIC ON) find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets Sql) qt_add_executable(StudentSystem main.cpp MainWindow.cpp MainWindow.h MainWindow.ui ) target_link_libraries(StudentSystem PRIVATE Qt6::Core Qt6::Gui Qt6::Widgets Qt6::Sql )如果在第 4.1 步勾选了 SQL 模块这里就不会报错。如果find_package报错说明 Qt 的 CMake 路径没有自动配置好回到 Qt Creator 的 Kits 页面检查编译器、Qt 版本、CMake 是否匹配。5.3 数据库连接代码在MainWindow.h里声明一个打开数据库的方法#ifndef MAINWINDOW_H #define MAINWINDOW_H #include QMainWindow QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACE class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent nullptr); ~MainWindow(); private slots: void openDatabase(); void updateStudentList(); private: Ui::MainWindow *ui; }; #endif // MAINWINDOW_HMainWindow.cpp里实现连接和下拉框填充逻辑#include MainWindow.h #include ui_MainWindow.h #include QSqlDatabase #include QSqlQuery #include QSqlError #include QSqlTableModel #include QDebug MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui-setupUi(this); openDatabase(); updateStudentList(); } MainWindow::~MainWindow() { delete ui; } void MainWindow::openDatabase() { QSqlDatabase db QSqlDatabase::addDatabase(QMYSQL); db.setHostName(127.0.0.1); db.setPort(3306); db.setDatabaseName(student_db); db.setUserName(qtuser); db.setPassword(123456); if (!db.open()) { qDebug() 数据库连接失败: db.lastError().text(); return; } qDebug() 数据库连接成功; } void MainWindow::updateStudentList() { QSqlTableModel *model new QSqlTableModel(this); model-setTable(student); model-setEditStrategy(QSqlTableModel::OnManualSubmit); model-select(); ui-tableView-setModel(model); }这一步可以看到 Qt 连接数据库的整个过程添加数据库驱动、设置连接参数、调用 open、创建 QSqlTableModel 把表映射到 QTableView。这是整个项目的最核心环节建议先在这里加日志输出确认数据库能连上再继续写界面。6. 核心功能实现界面设计6.1 设计主界面双击MainWindow.ui打开 Qt Designer。从左侧拖入以下控件顶部放一个QLineEdit用于输入查询关键词姓名。一个QPushButton文本写“查询”。中间放一个大QTableView用于显示学生数据。底部放四个按钮新增、修改、删除、刷新。布局可以参考-------------------------------------------------- | [姓名关键词 QLineEdit] [查询按钮] | -------------------------------------------------- | QTableView | | | -------------------------------------------------- | [新增] [修改] [删除] [刷新] | --------------------------------------------------给按钮设置好 objectName或者在代码里直接按类型查找。简单起见在 Qt Designer 里把按钮分别命名为btnQuerybtnAddbtnUpdatebtnDeletebtnRefreshlineEditKeyword6.2 查询功能实现在MainWindow.h增加槽函数private slots: void on_btnQuery_clicked(); void on_btnAdd_clicked(); void on_btnUpdate_clicked(); void on_btnDelete_clicked(); void on_btnRefresh_clicked();Qt 的自动连接机制允许你通过on_objectName_signal()的方式直接关联槽函数不需要手动 connect。在MainWindow.cpp实现查询void MainWindow::on_btnQuery_clicked() { QString keyword ui-lineEditKeyword-text().trimmed(); QSqlTableModel *model new QSqlTableModel(this); model-setTable(student); model-setEditStrategy(QSqlTableModel::OnManualSubmit); if (!keyword.isEmpty()) { model-setFilter(QString(name LIKE %%1%).arg(keyword)); } model-select(); ui-tableView-setModel(model); }这个查询就是 SQL 里的WHERE name LIKE %关键词%由 QSqlTableModel 帮你转成具体 SQL。注意setFilter的参数格式是 SQL 片段不要直接拼字符串防止 SQL 注入。如果你不想用 QSqlTableModel也可以直接写 QSqlQueryvoid MainWindow::on_btnQuery_clicked() { QString keyword ui-lineEditKeyword-text().trimmed(); QSqlQuery query; query.prepare(SELECT id, name, age, major FROM student WHERE name LIKE :kw); query.bindValue(:kw, QString(%%1%).arg(keyword)); if (!query.exec()) { qDebug() 查询失败: query.lastError().text(); return; } qDebug() 查询结果数量: query.size(); }两种方式都值得掌握QSqlTableModel 适合快速做标准 CRUDQSqlQuery 适合写复杂 SQL。建议新手先跑通 QSqlTableModel再自己写一遍 QSqlQuery 加深理解。6.3 新增功能实现新增数据可以弹出一个简单的输入窗口也可以简化逻辑在 QTableView 中直接进入编辑状态然后调用 submit。这里给出一个更清晰的教学方式用一个简单的 QInputDialog 收集信息再执行 INSERT。void MainWindow::on_btnAdd_clicked() { QString name QInputDialog::getText(this, 新增学生, 姓名:); if (name.isEmpty()) { return; } bool ok false; int age QInputDialog::getInt(this, 新增学生, 年龄:, 18, 10, 100, 1, ok); if (!ok) { return; } QString major QInputDialog::getText(this, 新增学生, 专业:); if (major.isEmpty()) { return; } QSqlQuery query; query.prepare(INSERT INTO student(name, age, major) VALUES (:name, :age, :major)); query.bindValue(:name, name); query.bindValue(:age, age); query.bindValue(:major, major); if (!query.exec()) { qDebug() 新增失败: query.lastError().text(); return; } on_btnRefresh_clicked(); }这里使用了 Qt 的预编译语句和 bindValue这种方法比直接拼 SQL 更安全也是实际项目里推荐的做法。6.4 修改功能实现修改操作在 QTableView 的 Model/View 框架下很直观选中一行直接双击单元格编辑然后点保存。但为了演示这里做一个“选中当前行 - 弹出当前数据 - 修改后更新”的版本。先拿到当前选中的行索引void MainWindow::on_btnUpdate_clicked() { QModelIndex index ui-tableView-currentIndex(); if (!index.isValid()) { QMessageBox::warning(this, 提示, 请先选择要修改的行); return; } QSqlTableModel *model static_castQSqlTableModel *(ui-tableView-model()); QString name model-data(model-index(index.row(), 1)).toString(); int age model-data(model-index(index.row(), 2)).toInt(); QString major model-data(model-index(index.row(), 3)).toString(); QString newName QInputDialog::getText(this, 修改学生, 姓名:, QLineEdit::Normal, name); if (newName.isEmpty()) { return; } QSqlQuery query; query.prepare(UPDATE student SET name :name, age :age, major :major WHERE id :id); query.bindValue(:name, newName); query.bindValue(:age, age); query.bindValue(:major, major); query.bindValue(:id, model-data(model-index(index.row(), 0)).toInt()); if (!query.exec()) { qDebug() 修改失败: query.lastError().text(); return; } on_btnRefresh_clicked(); }使用 QSqlTableModel 做更新更简单但这里展示 QSqlQuery 的 UPDATE 写法能让你直接掌握 SQL 层的控制。6.5 删除功能实现删除同样先获取当前行然后通过主键 id 删除void MainWindow::on_btnDelete_clicked() { QModelIndex index ui-tableView-currentIndex(); if (!index.isValid()) { QMessageBox::warning(this, 提示, 请先选择要删除的行); return; } QSqlTableModel *model static_castQSqlTableModel *(ui-tableView-model()); int id model-data(model-index(index.row(), 0)).toInt(); QString name model-data(model-index(index.row(), 1)).toString(); QMessageBox::StandardButton result QMessageBox::question( this, 确认删除, QString(确定要删除学生 %1 吗).arg(name) ); if (result ! QMessageBox::Yes) { return; } QSqlQuery query; query.prepare(DELETE FROM student WHERE id :id); query.bindValue(:id, id); if (!query.exec()) { qDebug() 删除失败: query.lastError().text(); return; } on_btnRefresh_clicked(); }6.6 刷新功能实现void MainWindow::on_btnRefresh_clicked() { QSqlTableModel *model new QSqlTableModel(this); model-setTable(student); model-select(); ui-tableView-setModel(model); }这部分看起来简单但要注意 Qt 里 QTableView 的 model 如果被多次替换旧 model 需要记得释放。示例代码中每次 new 到 this 下由父子对象机制自动回收实际项目中也可以维护一个成员变量 model 指针避免反复创建。7. 运行效果与验证流程7.1 首次启动验证点击 Qt Creator 左下角的绿色三角按钮构建运行。启动后重点观察程序是否能正常打开窗口而不是闪退。日志区是否输出“数据库连接成功”。QTableView 是否显示 student 表已有的三条数据。如果日志输出“数据库连接失败”先检查 MySQL 服务是否启动。Windows 下打开“服务”确认MySQL80或者类似名字的服务状态是“正在运行”。7.2 功能测试清单测试项操作预期结果数据显示打开程序表格出现三条学生记录按姓名查询输入“张”点击查询只显示“张三”空关键词查询点击查询显示全部记录新增点击新增填写“赵六”专业“人工智能”表格出现新记录MySQL 中也能查到修改选中一行点击修改改姓名表格更新数据库同步更新删除选中一行点击删除并确认记录消失数据库同步删除主键自增新增后观察 idid 不重复自动递增7.3 判断代码是否成功判断标准只有一个界面操作后数据库里的数据真实发生了变化。所以你测试时最好开着 MySQL Workbench每操作一步就执行一次SELECT * FROM student;。如果界面显示正常但数据库没变大概率问题出在提交策略上。QSqlTableModel 默认使用OnRowChange编辑策略行切换时会自动提交如果设置成OnManualSubmit必须手动调用submitAll()。本项目的查询、增删改都直接操作 QSqlQuery不依赖 model 的提交所以如果用了 QSqlTableModel 做界面显示注意编辑策略的选择。8. 打包发布与部署项目开发完成后如果要在没有 Qt 环境的机器上运行需要做打包。Qt 提供windeployqt工具它会自动拷贝运行需要的 DLL。在 Qt Creator 里选择 Release 构建编译完成后打开构建目录cd build-StudentSystem-Desktop_Qt_6_5_3_MinGW_64_bit-Release windeployqt StudentSystem.exe如果你的命令行找不到 windeployqt需要把 Qt 的 bin 目录加入 PATH或者用完整路径调用D:\Qt\6.5.3\mingw_64\bin\windeployqt.exe E:\StudentSystem\build\release\StudentSystem.exe如果还使用了 MySQL 驱动MySQL 的 libmysql.dll 或者 libmariadb.dll 也要一并拷贝到 exe 目录。MySQL 安装目录里搜索libmysql.dllMySQL 8 常见位置是C:\Program Files\MySQL\MySQL Server 8.0\bin把它复制到打包目录。验证打包是否成功把整个 release 目录复制到另一台没有 Qt 的电脑双击 exe。如果提示找不到 Qt6Core.dll说明 windeployqt 没执行完整如果提示无法加载 MySQL 驱动说明 libmysql.dll 缺失。9. 常见问题与排查方法问题现象可能原因排查方式解决方案编译报错find_package(Qt6 REQUIRED COMPONENTS Sql)安装 Qt 时没勾选 SQL 模块重新打开 Qt 安装器确认组件重新安装并勾选 Qt SQL运行报错QSqlDatabase: QMYSQL driver not loadedQt 找不到 MySQL 驱动或 libmysql.dllqDebug 打印 available drivers确认 Qt SQL 插件存在检查 plugins/sqldrivers/qsqlmysql.dll连接 MySQL 报Authentication plugin caching_sha2_passwordMySQL 8 默认认证插件与 Qt 自带驱动不兼容查看 MySQL 用户认证方式创建 mysql_native_password 用户数据库显示中文乱码表字符集不是 utf8mb4执行SHOW CREATE TABLE student建表时指定 utf8mb4连接后执行SET NAMES utf8mb4Qt Creator 提示 No suitable kits found安装时没选编译器套件工具 → 选项 → Kits重新安装对应编译套件或者手动配置编译器路径程序启动后窗口打不开main.cpp 中app.exec()异常退出或主窗口未 show检查控制台输出确认MainWindow w; w.show();已调用查询按钮点击没反应自动连接命名错误检查槽函数命名槽函数必须叫on_btnQuery_clicked()或在代码里手动 connect新增数据失败MySQL 权限不足查看日志打印的 lastError给用户授权GRANT ALL ON student_db.* TO qtuserlocalhostRelease 包在别人电脑上无法运行缺少 Qt 依赖 DLL用 windeployqt 重新打包把 sqlite、sqldrivers 目录一起拷贝部分 MySQL 驱动无法加载libmysql.dll 与 Qt 位数不一致确认 exe 是 x64下载正确架构的 MySQL 连接库也可以直接使用 MariaDB Connector/C10. 最佳实践与学习建议10.1 数据库连接统一管理实际项目中不要在每个窗口里都写addDatabase(QMYSQL)数据库连接数量和连接名要统一管理。更好的做法是封装一个DatabaseManager单例类class DatabaseManager { public: static DatabaseManager instance() { static DatabaseManager manager; return manager; } bool connect() { QSqlDatabase db QSqlDatabase::addDatabase(QMYSQL, main_connection); db.setHostName(127.0.0.1); db.setPort(3306); db.setDatabaseName(student_db); db.setUserName(qtuser); db.setPassword(123456); return db.open(); } QSqlDatabase connection() const { return QSqlDatabase::database(main_connection); } };这样写的好处是同模块复用同一个连接避免频繁打开关闭数据库接口调用也更清晰。10.2 从界面模式升级到业务分离示例代码把所有逻辑都放在 MainWindow 里这是教学需要。第二个版本建议把数据库操作抽到独立的 Dao 层StudentSystem ├── UI 层MainWindow、Dialog 等 ├── Dao 层StudentDao封装增删改查方法 └── 数据库连接层DatabaseManager做到这一步你对 Qt 工程结构的理解就超过大多数入门练习者。10.3 扩展方向跑通最基本的数据显示和增删改查后可以继续尝试添加登录窗口校验用户名密码。换用 QSqlQuery 实现多表关联查询。把 Excel 数据导入到 MySQL。用 QChart 绘制年龄分布图表。添加导出 CSV 功能。把数据库操作放到子线程避免表格查询卡住界面。10.4 安全与合规提醒项目里出现的学生姓名、专业等数据开发时使用测试数据即可不要用真实个人信息。如果未来要做真实业务系统必须给用户名密码做加密存储数据库连接不能使用 root 账号要给业务应用创建最小权限账号。涉及 MySQL 数据和 Qt 应用的发布也需要注意软件许可证和隐私合规要求。11. 总结与下一步这个项目的价值在于用最小成本打通 C、Qt6 和 MySQL 三者的协作。你会在动手过程中遇到编译器配置、数据库驱动、界面布局、SQL 语句等一堆具体问题而解决这些问题的过程正是从“学过 C”到“能用 C 写软件”的关键一步。建议你按照这个顺序推进先不碰代码把 Qt 和 MySQL 装好把 SQL 建表语句执行一遍。在 Qt Creator 里新建项目只写数据库连接确认日志输出成功。把 QTableView 和 QSqlTableModel 跑通看到表格显示数据。再逐个实现查询、新增、修改、删除。最后打包发布让这个项目真正变成一个“成品”。最容易卡住你的不是 C 代码而是环境配置和 MySQL 驱动问题。遇到报错不要慌先看 Qt 程序日志输出的lastError()文本它已经告诉了你大部分答案。跑通之后可以把项目代码整理到 Git 仓库README 里写清楚环境版本、部署步骤和功能演示这就是一个完整的学习项目作品。如果做某个功能卡住了优先去 Qt 官方文档搜索对应类的说明。祝顺利跑通第一个 Qt MySQL 实战项目。