简介:这份基于C++与QT实现的养猪模拟游戏课程设计项目,围绕养猪场管理场景,完整覆盖猪圈分配、品种隔离、出栏补栏、体重增长模拟、文件存取与猪瘟传播等核心功能,适合高校计算机相关专业学生作为课设、大作业或期末项目参考。压缩包共45个文件,大小7.66MB,主要包含14个cpp源码、13个h头文件、2个ui界面文件、2个qrc资源文件及png/wav素材,并附有项目说明文档,结构清晰,便于直接导入Qt工程运行与二次修改。设计上使用链表管理猪圈生猪,自动分配猪圈与统计售价,支持任意查询猪圈猪只状态及近五年的销售、购入记录,并提供各品种数量、体重及饲养时间分布图;猪瘟传播模块以概率模型模拟同圈与相邻传染,可作为算法可视化与交互设计的示范。已有117人学习,对正在完成相关课设或想扩展Qt项目功能的学习者,具有直接借鉴价值。
1. 为什么是“养猪模拟游戏”:一门课设如何把 C++ 和 Qt 用到实处
每年课程设计选题季,总有一批同学对着题目列表纠结:管理系统太土、算法题太卷、网络编程又怕自己调不通。如果你手里正好握着“基于C++和QT开发的养猪模拟游戏”,那这其实是个被低估的宝藏题目。它表面是个游戏,内核却是一个完整的“面向对象设计 + GUI 事件驱动 + 数据持久化”综合训练,C++ 负责把养殖逻辑写成类,Qt 负责把状态画成界面,二者各司其职,天然适合拿来当作课程设计的主项目。
这类项目的核心诉求很直接:把猪的生长过程抽象成数据模型,让玩家通过喂食、清洁、防疫等操作影响猪的健康和体重,再用可视化界面实时展示状态。对于学生来说,它比“图书馆管理系统”更能展示设计能力;对于想补项目经验的开发者来说,它麻雀虽小、五脏俱全,QTimer 驱动的模拟循环、信号槽解耦、序列化存档都是以后做正式产品会反复用到的东西。这篇文章不假设你已经有现成代码,而是按“从零把课设立起来”的顺序,讲清楚怎么组织工程、怎么写核心逻辑、怎么把界面做像样、以及哪些坑必须提前避开。
2. 从空工程到可运行骨架:项目结构、构建方式与 C++/Qt 的版本选型
2.1 为什么用 Qt Widgets 而不是 QML:选型先想清楚
“QT开发”在热词里经常跟着 Qt Designer、Qt Creator 一起出现,不少新手第一步就会纠结界面用 Widgets 还是 QML。对于课程设计,我的建议是:默认选 Qt Widgets。原因不是 QML 不好,而是 QML 的 QML/JS 混合编程会引入第二套语法体系,课设答辩时老师更想看到你用 C++ 类组织逻辑,而不是把业务规则写在 QML 的 JavaScript 函数里。
Qt Widgets 方案的典型分层是这样的:视图层放 QMainWindow 和自定义 QWidget,控制层用信号槽连接按钮点击与数据变更,模型层写 Pig、Farm、GameEngine 等纯 C++ 类。这套结构和你以后写 Qt 桌面工具、甚至 Qt 嵌入式应用的思路完全一致。
提示:如果所在学校指定了 Qt 版本,优先按学校要求来;如果自己下载,建议选 Qt 5.15.2 LTS,稳定、资料多、和 Qt Creator 的配合也最省心。Qt 6 也能做,但一些第三方教程和旧代码里的写法需要微调。
2.2 用 CMake 组织课设工程:比 qmake 多一步,但值得
Qt Creator 默认支持 qmake 和 CMake 两套构建系统。qmake 的 .pro 文件确实简单,但如果你以后想把这个项目迁移到 CI 环境,或者别人用不同 IDE 打开,CMake 的兼容性更好。下面给出一份可以直接用的 CMakeLists.txt 骨架。
cmake_minimum_required(VERSION 3.16) project(PigFarmSimulator VERSION 1.0 LANGUAGES CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) # 自动包含 Qt 的 moc/uic/rcc 工具链 set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOUIC ON) set(CMAKE_AUTORCC ON) find_package(Qt5 5.15 REQUIRED COMPONENTS Widgets) set(SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src) set(INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include) add_executable(PigFarmSimulator ${SOURCE_DIR}/main.cpp ${SOURCE_DIR}/Pig.cpp ${SOURCE_DIR}/GameEngine.cpp ${SOURCE_DIR}/MainWindow.cpp ${INCLUDE_DIR}/Pig.h ${INCLUDE_DIR}/GameEngine.h ${INCLUDE_DIR}/MainWindow.h ) target_include_directories(PigFarmSimulator PRIVATE ${INCLUDE_DIR}) target_link_libraries(PigFarmSimulator PRIVATE Qt5::Widgets)这段 CMake 配置里有三个关键点要理解:AUTOMOC 开启后,Qt 的信号槽元对象编译由 CMake 自动处理,不需要手动运行 moc;AUTOUIC 解决 .ui 文件到 ui_xxx.h 的转换;find_package 里的 5.15 必须和系统里安装的 Qt 版本一致,否则后面会报“fatal: cannot mix incompatible qt library”这类版本冲突错误,这个坑我们在第五章还会展开。
2.3 类的划分:从“猪”这个对象开始
课程设计源码里最重要的不是界面好不好看,而是类的职责是否清晰。以养猪模拟为例,最起码要拆出四个类:
- Pig:单头猪的数据模型,包括体重、健康值、饱食度、清洁度、成长阶段。
- GameEngine:模拟引擎,负责时间推进、随机事件生成、状态迭代。
- MainWindow:主窗口,承载所有 UI 控件,转发用户操作。
- 辅助结构体(或类):存档数据包,用于序列化和读档。
这里给出 Pig 类的头文件示例,关键成员全部用私有封装,对外只暴露接口。
#ifndef PIG_H #define PIG_H #include <QString> #include <QDateTime> class Pig { public: enum class GrowthStage { Piglet, // 仔猪 Growing, // 中猪 Adult, // 成猪 Ready // 出栏 }; Pig(const QString& name); void feed(double amountKg); void clean(); void vaccinate(); void updateDaily(); double weight() const; double health() const; double satiety() const; double cleanliness() const; GrowthStage stage() const; int ageDays() const; private: QString m_name; double m_weightKg = 5.0; double m_health = 100.0; double m_satiety = 80.0; double m_cleanliness = 100.0; int m_ageDays = 0; void recalcStage(); }; #endif // PIG_H这个头文件展示了一个课设项目应有的“数据边界”:界面代码永远不直接操作 m_weightKg,而是调用 feed 或 updateDaily。这不仅是面向对象封装的要求,更是后面做存档读写时能省力的前提。updateDaily 里要放每天的状态衰减和成长计算,feed 里要处理“吃太多反而生病”的平衡逻辑,这些细节直接决定游戏好不好玩,也是答辩时能讲出内容的地方。
2.4 main.cpp:让 QApplication 成为程序起点
C++ 的 Qt 程序入口和普通控制台程序不同,必须创建 QApplication 实例,然后进入事件循环。这个机制是 Qt 一切信号槽和定时器的基础,也是初学者最容易忽略“为什么窗口一闪而过”的根本原因。
#include <QApplication> #include "MainWindow.h" int main(int argc, char *argv[]) { QApplication app(argc, argv); MainWindow window; window.show(); return app.exec(); }app.exec() 启动事件循环后,程序才会持续响应按钮点击、定时器超时和窗口重绘。如果把 window.show() 写成了 window.showWindow(),编译会立刻报错;但如果你忘了调用 show,程序不会报错,只会出现一个“幽灵进程”——窗口不出现但进程不退出。这类问题的排查思路是:先看 main 函数是不是正确进入了事件循环,再去看控件是否被添加到了布局里。
3. 把“养猪”做成模拟器:状态系统、定时器循环与随机事件
3.1 设计一天的时间粒度:Tick 还是按秒模拟
模拟游戏的“时间感”是靠定时器驱动的,Qt 里最常用的是 QTimer。常见做法是设定一个游戏内 tick 等于现实时间的 1 秒,也就是每个 QTimer 超时信号代表游戏中过去了 1 天。这里的关键参数是 setInterval(1000),1000 毫秒触发一次 timeout 信号。
在 GameEngine 里通常会有这样的循环更新逻辑:对每一头猪依次执行 updateDaily,再检查是否触发随机事件,最后发出一个 stateUpdated 信号,通知界面刷新。这套流程和实时策略游戏的“心跳逻辑”是同构的,只是规模小得多。
void GameEngine::onTick() { m_dayCounter++; for (auto& pig : m_pigs) { pig.updateDaily(); addRandomEventsFor(pig); } emit stateUpdated(m_dayCounter, m_pigs); }这个函数写在 GameEngine 内部,通过 connect 把它连到 QTimer 的 timeout 信号上。关键点在于:不要在 onTick 里直接操作 QLabel 或 QProgressBar,因为引擎层根本不认识界面控件。它只负责改变数据,然后发信号,由 MainWindow 里面的槽函数把数据映射到控件上。这样做的好处是把“游戏规则”和“UI 表现”拆开,后续无论改成命令行版还是网页版,核心逻辑都能复用。
3.2 体重增长与健康值:用分段公式,别用一条直线
课设答辩时老师常问的一个问题是“你的游戏平衡性怎么设计的”。如果你说“每天体重加 1 公斤,健康值减 2”,那就太单薄了。更合理的做法是按成长阶段分段设定增长速率,同时引入健康值对增长速度的修正。
void Pig::updateDaily() { m_ageDays++; // 饱食度每日自然消耗 m_satiety = qMax(0.0, m_satiety - 8.0); // 清洁度每日自然下降 m_cleanliness = qMax(0.0, m_cleanliness - 5.0); // 健康不独立变化,而是根据前两项推导 if (m_satiety < 20.0 || m_cleanliness < 30.0) { m_health = qMax(0.0, m_health - 5.0); } else { m_health = qMin(100.0, m_health + 2.0); } // 体重增长受健康系数和阶段影响 double healthFactor = m_health / 100.0; double dailyGain = 0.0; switch (m_stage) { case GrowthStage::Piglet: dailyGain = 0.6; break; case GrowthStage::Growing: dailyGain = 1.2; break; case GrowthStage::Adult: dailyGain = 0.8; break; case GrowthStage::Ready: dailyGain = 0.2; break; } m_weightKg += dailyGain * healthFactor; recalcStage(); }这个 updateDaily 里的减法用了 qMax 带下限保护,防止数值变成负数。体重增长用的是“阶段系数 * 健康系数”的乘法模型,比固定增量更接近真实养殖规律——猪在成长期长得最快,成熟后增速放缓。这正是答辩时能拉开差距的设计细节。健康值不是独立随机数,而是饱食度和清洁度的衍生值,这会让玩家感受到“操作影响状态,状态影响结果”的因果关系。
3.3 随机事件:把课设从“展示品”变成“可玩项目”
一个没有随机事件的养猪模拟,玩起来就像进度条,玩家点几下就腻了。加入随机事件是提升可玩性的最便宜手段。常见事件包括:猪突然食欲下降、天气变化导致清洁度降低、发现猪腹泻需要治疗、市场价格波动影响出栏收益。随机事件在 Qt 里只需要用 QRandomGenerator,这是 Qt 5.10 之后推荐的随机数接口。
void GameEngine::addRandomEventsFor(Pig& pig) { auto* rng = QRandomGenerator::global(); // 5% 概率触发食欲下降事件 if (rng->bounded(100) < 5) { emit eventTriggered(pig.name(), "食欲下降"); pig.adjustSatiety(-15); } // 3% 概率触发天气事件,影响清洁度 if (rng->bounded(100) < 3) { emit eventTriggered(pig.name(), "暴雨"); pig.adjustCleanliness(-10); } }QRandomGenerator::global() 是全局线程安全的随机数生成器,bounded(100) 返回 0 到 99 的整数,所以 5% 概率就是小于 5。注意这里不要自己用 rand() 和 srand(),因为 Qt 的事件循环和渲染线程可能对全局状态有干扰,用 Qt 自带的生成器更稳妥。事件触发后,通过 eventTriggered 信号把文本消息推给界面,让 UI 显示一条日志,这样玩家就知道发生了什么。
3.4 存档与读档:用 QJsonDocument 做序列化
课程设计的加分项之一就是“关闭程序再打开,游戏还在”。实现存档最可靠的方式是 JSON 格式,Qt 的 QJsonDocument 可以方便地把嵌套结构写成文件。你可能听说过 QSettings 也能做,但 QSettings 更适合存配置,而存档这种结构化的数据用 JSON 更清晰。
bool GameEngine::saveGame(const QString& filePath) { QJsonObject root; root["day"] = m_dayCounter; QJsonArray pigArray; for (const auto& pig : m_pigs) { QJsonObject pigObj; pigObj["name"] = pig.name(); pigObj["weight"] = pig.weight(); pigObj["health"] = pig.health(); pigObj["satiety"] = pig.satiety(); pigObj["cleanliness"] = pig.cleanliness(); pigObj["age"] = pig.ageDays(); pigArray.append(pigObj); } root["pigs"] = pigArray; QFile file(filePath); if (!file.open(QIODevice::WriteOnly)) { return false; } file.write(QJsonDocument(root).toJson()); file.close(); return true; }方法里用 QJsonObject 组装数据结构,再用 QJsonArray 保存猪的列表,最后通过 QJsonDocument::toJson 一次性写成带缩进的文本文件。读档的过程基本就是反向操作,唯一要注意的是 QJsonValue 的类型转换,如果读出来是空值,就说明 JSON 字段名对不上,这种问题在后续维护里最容易遇到,调试时可以先把文档 qDebug 出来看看。
4. 让界面“活”起来:Qt Designer 布局、状态刷新与用户交互
4.1 用 Qt Designer 搭静态骨架,别用手写代码堆控件
如果你还在用代码逐个 new QLabel 和 QPushButton,那效率太低了。Qt Designer 的 .ui 文件可以直接拖拽布局,生成后 AUTOUIC 会自动编译到项目里。课程设计里我一般建议手动把整体框架分成左、中、右三块:左侧放猪的信息面板,中间放主视图,右侧放操作按钮和事件日志。
在设计器里要注意的一个坐标参数是 sizePolicy,它会决定控件在窗口缩放时的行为。猪的信息面板建议设置成 Expanding,操作按钮设置成 Preferred,这样窗口拉大时信息面板会摊开,按钮区保持紧凑。这个细节在平时看不出差别,但放到高分屏上或者答辩投影时,观感差距会非常明显。
4.2 进度条与状态面板:把 Pig 的数据映射到 UI
界面的核心作用是把 Pig 对象的四个关键数值——体重、健康、饱食度、清洁度——实时呈现出来。QProgressBar 非常适合表现 0 到 100 的状态值,而体重需要转换成整数再显示成文本。
void MainWindow::onStateUpdated(int day, const QVector<Pig>& pigs) { m_dayLabel->setText(QString("第 %1 天").arg(day)); const Pig& pig = pigs.first(); m_weightLabel->setText(QString("%1 kg").arg(pig.weight(), 0, 'f', 1)); m_healthBar->setValue(static_cast<int>(pig.health())); m_satietyBar->setValue(static_cast<int>(pig.satiety())); m_cleanBar->setValue(static_cast<int>(pig.cleanliness())); // 根据健康值调整进度条颜色,低于 30 显示红色 if (pig.health() < 30.0) { m_healthBar->setStyleSheet("QProgressBar::chunk { background: #e74c3c; }"); } else { m_healthBar->setStyleSheet(""); } }arg 的第二个参数 0 表示最小宽度为 0,'f' 表示浮点数格式,1 表示保留一位小数。把 double 转成 int 再传给 setValue 是因为进度条的 value 是整数类型。颜色变化用 setStyleSheet 动态调整,这里不推荐直接在构建时写死样式,因为状态不同时期显示不同的颜色,才能给玩家直观的预警感。这段槽函数通过 connect 连接到 GameEngine 的 stateUpdated 信号,就完成了数据到界面的单向流动。
4.3 用户操作:按钮如何最终改变猪的状态
用户点击“喂食”按钮后,事件链路是这样的:按钮的 clicked 信号触发 MainWindow 里的一个私有槽,槽函数调用 GameEngine 的 feedCurrentPig 方法,GameEngine 修改 Pig 对象,然后立刻发出 stateUpdated 信号,界面随之刷新。这中间没有哪一行代码是“直接改控件”的。
void MainWindow::onFeedButtonClicked() { double amount = m_feedAmountSpin->value(); m_engine->feedCurrentPig(amount); appendLog(QString("你给 %1 喂了 %2 kg 饲料") .arg(m_engine->currentPigName()) .arg(amount)); }这里引入 QDoubleSpinBox 作为喂食量输入控件,而不是用固定的按钮点击一次加 10 克,能让玩家对“操作力度”有感知。appendLog 是自定义的日志函数,往 QPlainTextEdit 里追加一行,并将光标移到底部,这样玩家能一直看到最新的反馈日志。这种“操作后立刻通过信号刷新全部状态”的模式,比手动逐个更新控件代码量少得多,而且结构上不容易漏刷新。
4.4 状态刷新方案:一次性全量更新还是增量更新
有的课设会把刷新做成增量式,比如只更新被修改过的猪。但在这个项目里,猪的数量通常小于 10 头,全量更新完全够用。我建议直接每次发送整个 pigs 向量,界面遍历刷新所有控件。这个选择能让代码更简单可靠,把精力省下来去处理更有价值的问题。
如果你打算做多猪同场养殖,那就要注意:全量刷新时不能重建整个布局或删除所有控件。正确做法是维护一个猪信息卡片列表,按索引去更新已有卡片的 QLabel 文本,而不是 clearLayout 再重建。后者会造成界面闪烁,而且不停地 new 对象会带来内存压力。
5. 避坑清单:课设里最容易翻车的 6 个“玄学”问题
5.1 Qt 版本混用导致链接失败
现象:在别人电脑上能编译,到自己电脑上报错:fatal: cannot mix incompatible Qt library (version ex50601) with this library,或者一连串 undefined reference。
原因:最常见的是系统里装了多个 Qt 版本,CMake 的 find_package 找到了一个版本,而编译器实际链接的是另一个版本。还有就是 Qt 5.15 与 Qt 6 混用,它们虽是相似接口,但底层 ABI 不同,绝对不能混链。
解决:先彻底卸载多余版本,或用 Qt 自带的 MaintenanceTool 清理。然后在 CMakeLists 中明确写 find_package(Qt5 5.15 REQUIRED),并在 Qt Creator 的构建套件(Kit)里指定同一个 Qt 版本的 qmake 路径。检查构建输出里 qmake 的路径,确保和 CMake 找到的路径一致,这个检查能节省大量排查时间。
5.2 中文路径导致构建失败或运行时找不到插件
现象:项目目录放在 D:\课程设计\PigFarm,编译时出现无法找到文件,或运行时报 could not find the qt platform plugin "windows"。
原因:Qt 的构建工具链对中文路径支持不是完美无缺,尤其是某些老版本 MinGW 在解析带中文的路径时会出乱码,导致临时文件无法生成。运行时找不到 platform plugin 也有可能是环境变量 QT_QPA_PLATFORM_PLUGIN_PATH 指向了错误的插件目录。
解决:课程设计项目目录全用英文。这里想确认一下,你刚才提到的目录结构,是直接把整个项目放在 D:\ 下面,还是在 D:\ 下建了一个英文文件夹再放项目?通常建议是 D:\PigFarm 或 C:\workspace\PigFarm。如果是在中文目录下开发的,先把整个项目复制到英文路径再重新编译。同时,在 Qt Creator 的“运行”设置里检查工作目录是否含中文,很多隐藏的启动失败都源于此。
5.3 QTimer 回调里操作已销毁的控件导致崩溃
现象:游戏运行过程中,点击关闭窗口,程序崩溃,断点定位在某个 setText 调用附近。
原因:窗口关闭时,QTimer 没有停止,定时器回调还在触发,而回调函数里访问的控件已经被销毁。这是 Qt 事件循环一个典型的使用误区——对象销毁顺序没处理好。
解决:在 MainWindow 的析构函数中显式调用 m_timer->stop(),或者更好的是利用 QObject 父子机制:把 QTimer 的 parent 设为 MainWindow,但析构时也要显式停掉,因为 stop 和 delete 是两回事。更稳妥的做法是设置窗口关闭时退出事件循环。
MainWindow::~MainWindow() { m_timer->stop(); }这个析构函数写在 MainWindow 里,建议在窗口关闭前就把定时器停掉。注意,如果你在 closeEvent 里 deleteLater 了某些控件,也要保证不会再有信号触发它们的方法。
5.4 中文字符串在界面上显示为乱码
现象:窗口标题、按钮文字都是问号或乱码,但控制台输出正常。
原因:代码文件本身保存编码和编译器默认执行字符集不一致。Qt 5 默认假定源码是 UTF-8,但 MSVC 编译器在没有 /utf-8 选项时会把源码按本地代码页(GBK)解析。
解决:在 CMakeLists 中加入针对 MSVC 的编译选项。
if(MSVC) add_compile_options("/utf-8") endif()这个是 CMake 的标准写法,通过判断编译器版本,为 MSVC 环境添加 UTF-8 编译参数。如果你用的是 MinGW,一般不会出现这个乱码问题,因为 MinGW 默认就是 UTF-8。另一个小技巧是,所有界面字符串都放在 QStringLiteral 或 tr() 里,不要直接用 char* 拼接中文。
5.5 高 DPI 缩放下界面模糊或按钮变形
现象:在 2K 或 4K 屏幕上,窗口显示出来字很小,图片模糊,布局挤压。
原因:Qt 5.6 后默认支持高 DPI,但如果你没有设置 setAttribute(Qt::AA_EnableHighDpiScaling),在部分平台上仍会按 96 DPI 来渲染。
解决:在 main.cpp 的 QApplication 创建之前设置属性标志。这是 Qt 官方支持的写法,可以让程序在 Windows 和 Linux 上自动适配缩放。注意要在创建 QApplication 之前设置,否则不会生效。如果你开发环境下一切正常,到答辩机器上变模糊,优先检查这条。
5.6 存档文件打不开或读出来是空数据
现象:saveGame 返回 true,但 loadGame 之后所有数值都是 0。
原因:多因为 JSON 字段名拼写不一致。比如保存时写的是 weight,读取时用的是 weightKg,QJsonValue 读不到 key 时返回的是空值,而空值转 double 就是 0。
解决:把保存和读取的 JSON 字段名统一抽成常量,不要在两个函数里各写一遍字符串。更简单的方法是保存时直接用结构体转 QJsonObject,读取时也按同一个结构体反向解析。调试时在加载函数最后用 qDebug() << QJsonDocument(root).toJson() 打印一次,看看内容是否完整。
6. 收尾技巧:从“能跑”到“值得展示”的测试、数据可视化与答辩加分
项目代码都正常跑通之后,还有几件事能显著拉开和其他课设的差距。第一件是主动写测试用例,虽然很多人觉得课设不需要测试,但只要有几个断言来验证核心逻辑,比如“喂食后饱食度不超过 100”“健康值低于 20 时体重停止增长”,就能证明你的代码是可验证的,这在答辩时很加分。
第二件是把数据可视化做得更有说服力。我建议在 UI 里加入一个简单的折线图,显示猪的体重随天数增长的趋势。Qt 里可以引入 Qt Charts 模块,或者自己用 QPainter 画一个二维坐标折线。如果不想引额外模块,用 QCustomPlot 也可以,但那是第三方库,需要额外说明来源。手动画线的成本其实很低,用 QPainter 的 drawLine 把历史体重逐点连接起来,再加两条辅助线标记出栏标准,三五十行代码就能完成。
第三件事是准备一份项目说明文档,重点写清楚:类的职责划分、信号槽的通信链路、模拟引擎的时间循环、存档格式设计。文档里不要大段贴代码,而是画清楚调用关系。比如“点击喂食按钮后 clicked 信号触发 MainWindow::onFeedButtonClicked,该方法调用 GameEngine::feedCurrentPig,进而修改 Pig 对象并触发 stateUpdated 信号,最终刷新 UI”这段链路写明白,答辩基本就能立于不败之地。
最后提醒一下工作目录和发布路径的匹配问题。我见过不少项目在开发环境跑得好好的,拷到别的机器上就报“could not find the qt platform plugin”错误,这是因为 Qt 的发布需要带上对应的 plugins 目录。如果你用 windeployqt 发布,注意它生成的是针对当前构建套件的插件版本,用的是 debug 库打包就会缺失 release 插件。发布给老师看的时候,建议打一个 release 包,再用 windeployqt 部署到单独的目录,不要直接拷贝整个构建目录。
这些技巧里我印象最深的是那次因为 MSVC 编码问题导致整个界面的中文全部变成了问号,当时以为是 Qt 安装坏了,重装了两次 Qt 才反应过来是编译参数的问题。后来养成习惯,新项目第一件事就是把 /utf-8 选项写进 CMakeLists。希望这个习惯也能帮到你,如果你的课设正在赶工,有一条路径值得优先走:先把纯逻辑代码写完并用 qDebug 验证,再套上 Qt Widgets 界面。祝你的养猪场早日出栏。
本文还有配套的精品资源,点击获取