最近有朋友问我:Qt 到底怎么新建工程?他说自己把 Qt Creator 装好了,结果打开软件,面对一堆模板和选项完全不知道该点哪里。这个问题看起来基础,但我在带新人时发现,能在这一步顺畅走完、并且真正理解每个选项含义的人,其实不多。很多人是靠着记忆硬记“点这个、点那个”,换台机器换个版本就卡住。
这篇内容就把 Qt 创建新工程这件事从头到尾捋一遍。从版本和编译器怎么匹配,到向导每一步该选什么,再到工程文件怎么拆解、第一次编译报错怎么处理,一步不落。适合刚接触 Qt 的初学者,也适合已经在写 Qt 代码但一直没搞懂工程结构的人。我尽量用大白话讲清楚背后的原理,这样你以后再遇到 Qt Creator 的不同版本、不同构建系统,也能自己判断该怎么选。
1. 动手之前先想清楚:Qt版本、编译器和Kit的匹配关系
1.1 版本选择:不要太新也不要太旧的稳妥策略
很多人装 Qt 时第一步就蒙了:官方下载页面有一堆版本号,5.x 有、6.x 也有,而且每个版本还要对应不同的编译器组件。
我的建议很简单:除非有明确的项目兼容需求,否则直接选择当前官方在线安装器里默认提供的稳定版本。新版带来了大量改进,比如 Qt 6 把很多模块重新整理过,对 C++ 标准的支持也更好,以后生态只会越来越向它看齐。如果你刚学或者做新项目,没必要从已经处于维护末期的老版本起步。
但这不意味着建议你追最新的预览版或者 Beta 版。学习和开发用的版本,稳定性比新鲜感重要。官方标注为稳定版、能被在线安装器正常拉取的就是合适的选择。
另外要注意开源版与商业版的问题。个人开发者、学习用途,通常用开源版本就够了,功能没有阉割,只是授权方式不同。正常使用和开发完全没问题,我也是这么一路走过来的。
1.2 编译器与Kit:新手最容易漏掉的一环
确认完 Qt 版本,下一个问题就是:你电脑上得有对应的编译器。Qt 库不是纯头文件库,编译最终程序时,编译器会把你的 C++ 代码和 Qt 库链接在一起。编译器版本、位数与 Qt 库不一致,就会产生一堆让人摸不着头脑的报错。
在 Windows 上,通常有两个选择:
- MinGW,也就是 GCC 的 Windows 移植版,Qt 官方会提供配套的 MinGW 工具链。装好就能用,不需要额外配置 Visual Studio,对新手最友好。
- MSVC,也就是微软的 Visual C++ 编译器。特点是 Windows 平台兼容性最好、调试信息丰富,但需要你机器上有对应的 Visual Studio 环境,或者至少安装了 Build Tools。
安装 Qt 时,很多人只勾选了 Qt 组件本身,忘了勾选对应编译器的组件。结果打开 Qt Creator 一看,找不到任何可用的套件,菜单里灰蒙蒙一片。这就是典型的新手问题。安装向导里,凡是带“MinGW”或“MSVC”字样并且版本匹配的组件,最好一并勾上,同时还要把“Qt Creator”和“CMake”这类基础工具勾上,否则后面某些功能会缺失。
提示:这里说的“套件(Kit)”,本质就是一组配置的集合,里面绑定了编译器、调试器、Qt 版本和 CMake 等工具的路径。Qt Creator 就是靠 Kit 来决定“用哪个编译器去编译哪一套 Qt 库”。所以 Kit 选错、或者 Kit 缺失,后续一系列编译问题都会冒出来。
另外,32 位和 64 位也要提前统一。现在大多数电脑都是 64 位系统,我见过有人不小心装了 64 位 Qt 库,却选了 32 位编译器,结果程序一启动就报错,错误码 “0xc000007b”。这种问题排查起来非常浪费时间。所以从一开始就确认自己的系统位数,然后所有组件都统一,别混着来。
路径问题在这里也可以一并提一下:安装路径和工程路径,尽量别带上中文、特殊符号。某些编译工具对非 ASCII 路径支持不好,报错时的提示又很抽象,很难联想到是路径问题。我个人的习惯是统一用一个纯英文的目录放所有 Qt 工程文件,省心。
2. 新建工程的完整路径:从打开向导到第一个窗口跑起来
2.1 模板选择:四个最常见的入口应该怎么选
装好环境后,进入正题。打开 Qt Creator,点击左上角“File”菜单里的“New Project”,或直接按Ctrl+N。这时会弹出一个向导窗口,左侧是模板分类,中间是具体模板。很多人就是在这一步开始发懵的。
对新工程来说,最常见的入口有这么几个:
- Qt Widgets Application:传统桌面 GUI 程序。界面用 QWidget 体系构建,通过
QMainWindow、QDialog这些窗口类组合控件。C++ 桌面应用大部分场景都用它,也是新手学习 Qt 的首选。 - Qt Quick Application:基于 QML 和 QQuickView 的界面程序。QML 是一种声明式语言,做动画、做流畅的现代界面非常方便。界面复杂、视觉效果强的项目推荐它,但入门门槛比 Widgets 稍微高一点。
- Qt Console Application:无界面命令行程序。适合写工具、写后台服务、写算法测试。它也会创建一个完整工程,但没有界面部分。
- 空项目 Empty qmake Project(或空白 CMake 工程):所有文件都需要自己添加。适合对工程结构已经完全掌握的人,不建议零基础从这里开始。
如果你是初学者,我会推荐直接选 Qt Widgets Application,因为它能最快让你看到一个可以运行的窗口界面,学习路径最平滑。等把工程结构、信号槽这些东西都搞明白了,再回头尝试其他模板也不迟。
2.2 向导中的关键设置:工程名、路径、类和套件
选定模板后,向导会连续追问几屏信息,每一屏都不能无脑点下一步。
第一屏是工程名(Name)和创建路径(Create in)。工程名建议用英文,大小写习惯用驼峰形式,比如MyFirstApp。这里有个重要细节:Qt Creator 会自动在“Create in”指定的目录下,再创建一个以工程名命名的子目录来存放工程文件。所以你在选择路径时直接选一个“总目录”就好,不用担心工程文件会散落一地。
接着会让选择构建系统。在 Qt Creator 新版本里,默认一般会偏向 CMake。构建系统这步很重要,我后面单独用一个章节讲,这里先按住不表。
如果选的是 Widgets Application,向导还会问类名和基类。默认会生成一个MainWindow类,基类是QMainWindow。基类有QMainWindow、QWidget、QDialog三个常见选项。三者的差异简要来说:QMainWindow 自带菜单栏、状态栏、工具栏等大窗口框架;QWidget 是最基础的窗口控件,没那么多框架;QDialog 专为对话框设计。初学者先用 QMainWindow 比较合适,因为它的结构最完整,后续加菜单、加状态栏都直接在模板基础上改。
然后是 Kit 选择页。这里列出你当前电脑上所有可用的套件。正常安装的话,会看到一个类似于 “Desktop Qt 6.x.x MinGW 64-bit” 的选项,勾上它,继续。如果这里一个 Kit 都没有,回到第 1 章讲的编译器和 Qt 库不匹配的问题里排查。
最后还有一屏版本控制系统配置,默认是 None 或者 Git。这个不影响工程创建,如果你以后打算用 Git 管理代码就在这里选上,没有就跳过。
2.3 点击Finish后发生了什么:构建系统、目录与运行验证
点击 Finish 之后,Qt Creator 会立刻生成工程骨架,并在左侧文件树里展示所有文件。不同模板生成的文件不同,以 Widgets Application + CMake 为例,通常会有CMakeLists.txt、main.cpp、mainwindow.cpp、mainwindow.h、mainwindow.ui这几个文件。qmake 模板则会把CMakeLists.txt换成.pro文件。
这时的工程还没有被编译。点击左下角绿色的运行按钮(快捷键Ctrl+R),Qt Creator 会自动执行构建系统,然后编译、链接、运行。第一次编译因为要生成大量中间文件,会稍微慢一点。如果一切顺利,屏幕上会弹出一个带标题栏的空白窗口。到这里,你的第一个 Qt 工程就算是正式建好了。
这里要特别提醒一个习惯:第一次创建工程后,先什么都别改,直接跑一遍。确认“是否报错”“是否弹窗”“窗口能否关闭”都没问题后,再开始写业务代码。这样就切分清楚了:环境问题归环境问题,代码问题归代码问题。不要上来就改一堆代码再运行,到时候报错了,你也分不清是工程配置问题还是自己代码写错了。
3. 构建系统选择:qmake还是CMake,影响着后面每一个编译环节
3.1 qmake:简单直接,和Qt绑定最紧密
qmake 是 Qt 官方最早提供的构建工具,使用.pro文件来描述工程。语法非常简洁,比如:
QT += core gui greaterThan(QT_MAJOR_VERSION, 4): QT += widgets TARGET = MyFirstApp TEMPLATE = app SOURCES += main.cpp \ mainwindow.cpp HEADERS += mainwindow.h FORMS += mainwindow.uiQT指定用哪些 Qt 模块,TARGET指定生成的目标文件名,TEMPLATE指定构建的是应用程序还是库,SOURCES、HEADERS、FORMS分别罗列要参与编译的代码文件。
qmake 最大的优点是简单、隐式处理了很多 Qt 特有的步骤。比如当你写了一个带Q_OBJECT宏的类,qmake 会自动生成元对象编译(moc)所需的中间流程,你不需要关心这些细节。对于单个 Qt 工程、没有复杂依赖的项目,用 qmake 非常舒服,一看就懂。
3.2 CMake:通用生态与Qt 6的默认选择
CMake 本身和 Qt 没有任何绑定关系,它是通用 C++ 生态里的事实标准跨平台构建系统。Qt 6 时代开始,官方把 CMake 作为主推的构建系统,Qt Designer 里新建工程也会默认偏向 CMake。
一个简单的 CMakeLists.txt 长这样:
cmake_minimum_required(VERSION 3.16) project(MyFirstApp VERSION 0.1 LANGUAGES CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) find_package(Qt6 REQUIRED COMPONENTS Widgets) qt6_add_executable(MyFirstApp main.cpp mainwindow.cpp mainwindow.h ) target_link_libraries(MyFirstApp PRIVATE Qt6::Widgets)比起 qmake,CMake 显得啰嗦一点,它要求你更显式地声明很多东西:C++ 标准、Qt 模块、源文件列表、链接目标等。但这份显式恰恰是它在大型项目中的优势:依赖关系清楚,扩展模块容易,第三方库集成成熟。
逻辑上其实可以把 CMake 理解为“构建系统的构建系统”——它本身不直接编译代码,而是根据 CMakeLists.txt 生成对应平台的原生构建文件(比如 Makefile 或 Ninja),再交给 make 或 ninja 去真正执行编译。
3.3 不同场景下的选型建议
那到底选哪个?说句实话,这个问题在 Qt 社区里争论很多。我给出一个比较务实的判断标准:
- 如果你只是在 Qt 范围内写一些中小型工具、学习练习,工程结构简单,希望配置文件越少越好,选 qmake 完全够。
- 如果你的工程需要引入大量第三方 C++ 库、团队采用统一构建规范、或者在用 Qt 的同时还要处理很多非 Qt 的代码,优先选 CMake。
- 如果公司团队工程项目有规定,那就跟随团队,别自己另搞一套。
上面说的是逻辑上的选择逻辑。但现实还有一个因素要面对:Qt Creator 新版默认给 CMake,你以后查资料、问 AI、找别人的工程示例,CMake 的例子会越来越多,qmake 的资料正在快速变少。如果是完全没有偏好的新人,我建议直接走 CMake,因为你需要参考的文档和案例会更容易找到。
4. 新建工程生成了哪些文件:骨架代码逐一拆解
4.1 main.cpp:你真正该有的程序入口
创建完工程后,第一个要看的文件就是main.cpp。Widgets 模板生成的代码大致是这样:
#include "mainwindow.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.show(); return a.exec(); }这个程序入口是全工程的核心。QApplication负责初始化 Qt 的运行环境,管理事件循环、窗口系统资源。argc和argv是命令行参数,QApplication构造时会接收它们,这样你的程序以后就能正确处理命令行传入的参数。
w.show()这一行很多人看了没感觉,但它很关键。新建出来的窗口默认是不可见的,如果不调用show(),程序运行起来什么都不会显示,而且因为事件循环还在跑,你不会看到任何报错,只会看到程序“没反应”。我第一次写 Qt 时就犯过这个错,排查了半天才发现是忘了 show。
最后的a.exec()进入 Qt 的事件循环。程序从这个地方开始不会往下执行,而是不断处理用户点击、键盘、绘制等事件,直到窗口被关闭,这个函数才返回,程序才结束。理解了这行代码,很多“为什么 Qt 程序不会自己退出”的疑惑就能解开。
4.2 窗口类三件套:头文件、源文件与ui文件如何协作
模板生成的mainwindow.h、mainwindow.cpp、mainwindow.ui这三件套,是理解 Qt GUI 工程的关键。
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: Ui::MainWindow *ui; }; #endif // MAINWINDOW_H这里的Q_OBJECT是所有 Qt 信号槽类必须带的宏。它会触发 moc 工具生成一份额外的 C++ 代码,让类支持信号槽、反射等信息。新手会经常忘记写这个宏,结果信号槽连接不上,还没有编译错误提示,非常难受。
mainwindow.cpp是类的实现:
#include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); } MainWindow::~MainWindow() { delete ui; }这里有个隐藏流程:mainwindow.ui不是直接写进代码里的,而是一个 XML 格式的界面描述文件。构建时,uic 工具会根据.ui文件生成一个名为ui_mainwindow.h的 C++ 头文件。你在设计器里拖的控件,最终都会变成这个头文件里的代码。
所以 include 的是ui_mainwindow.h,而不是mainwindow.ui。这也是很多新手困惑的地方:为什么我改了.ui文件但代码里看不到控件?因为控件是在ui_mainwindow.h里动态生成的,你的源文件通过ui->setupUi(this)把界面装配到当前窗口上,然后就能用ui->控件名去访问它们。
4.3 工程配置文件:.pro文件里的字段到底在做什么
如果你选了 qmake 构建系统,向导会生成一个.pro文件。它看起来简单,但每个字段都有意义:
QT:声明要使用哪些 Qt 模块。core和gui是绝大多数工程都需要的。用了 QMainWindow、QPushButton 这些界面控件,必须加上widgets;如果用到网络需要加network,用到数据库需要加sql。漏掉模块,编译器会在头文件或链接阶段报错。TARGET:生成的可执行文件名称。默认和工程名一致。TEMPLATE:工程类型。app表示生成可执行程序,lib表示生成库。做插件或动态库时才会改它。SOURCES、HEADERS:告诉 qmake 哪些.cpp和.h要参与编译。手动新增一个类时,忘了同步添加这些文件,编译时就会出现链接错误。FORMS:UI 文件列表。CONFIG:附加配置项。比如把console加进去,程序运行时会显示控制台窗口;这个在调试命令行程序时很常用。
手动往工程里添加文件时,qmake 不会自动感应磁盘上新加的文件,你需要做一次“添加现有文件”的操作或直接修改.pro文件。这是新手很容易踩的坑。CMake 工程也会有类似的机制,不过 Qt Creator 通常会自动提示重新加载 CMakeLists。
4.4 构建目录为什么独立出来:影子构建机制
工程首次编译后,你会发现在工程目录同级多了一个名字类似于build-MyFirstApp-Desktop_Qt_6_x_x-MinGW_64_bit-Debug的文件夹。所有编译的中间文件和最终生成的 exe 都放在里面。这就是 Qt Creator 默认的“影子构建”机制。
影子构建的意思是:源码目录和构建目录分离。这样做有几点好处。一是源代码目录保持干净,你只需要把源码目录加入 Git,不用担心临时文件污染仓库。二是一个工程可以同时有 Debug 和 Release 两套构建,互不干扰。三是在磁盘上不小心删掉构建目录也没关系,重新编译一遍就行,不影响任何源码。
理解了这个机制,你就不至于在构建目录里找了半天源码,也不至于把构建目录整个拷走当成工程。
5. 第一次构建和运行的常见问题排错
5.1 运行后找不到Qt相关的DLL
新手最常遇到的情况:在 Qt Creator 里运行正常,但跑到编译输出目录里双击生成的 exe,弹出“由于找不到 Qt6Core.dll,无法继续执行代码”之类的提示。
原因很简单:程序在运行时要动态加载 Qt 的 DLL,而这些 DLL 放在 Qt 安装目录的 bin 文件夹下,Windows 默认搜索路径里没有它。Qt Creator 运行时能加载,是因为它会自动为程序设置运行环境变量。
解决办法也很固定:在 Windows 上使用官方提供的windeployqt工具,在命令行里切到编译输出目录,对生成的 exe 执行一次,它会把 exe 依赖的所有 Qt DLL 和各平台插件自动拷贝到同一目录。这样你整个目录拷给别人,在没有 Qt 的电脑上也能运行。
当然这只是发布方式之一。真正要交付软件时,更规范的做法是用安装包制作工具把所有依赖打包好,但 windeployqt 是理解依赖关系的最直观入口。
5.2 链接失败或头文件缺失的典型场景
编译报错里有一类非常典型:错误信息里带 “cannot find -lxxx” 或者 “No such file or directory: xxx.h”。这类问题绝大多数与 Qt 模块没写全有关。
举个例子,一个 Widgets 程序里用了QApplication,但.pro文件只写了:
QT += core gui没有widgets。Qt 6 里QApplication在 Widgets 模块中,编译时就会报找不到头文件,或者在链接阶段找不到符号。
在 CMake 里对应的错误是find_package没找到对应组件,或者target_link_libraries没把Qt6::Widgets链接进来。
排查流程我一般是这样:先看报错中提到的符号是什么类、哪个库,然后回去检查工程配置里到底有没有把这个模块加进来。不要一上来就怀疑代码逻辑,工程层面的东西先排除干净。
还有一种情况是手动添加了新的.cpp/.h文件,却没有同步更新到.pro或CMakeLists.txt里。表现为新写的类编译时报“undefined reference”。我一再跟身边人说:先看文件是不是真正被工程包含了,不参与编译的文件,写得再对也没用。
5.3 中文乱码、高DPI缩放和调试器缺失
中文乱码属于老生长谈。Qt 5 和 Qt 6 在源码编码上的默认处理不同,但最常见的情况是:Windows 下源文件使用 GBK 编码,源文件里写了中文,运行后界面或控制台全是乱码。解决思路是统一使用 UTF-8 编码。Qt Creator 的编辑器右下角可以修改文件编码,文件另存时选择 UTF-8 即可。
如果项目里长期要处理大量中文源码,我习惯在.pro或 CMake 里做一层强制编码设置(比如 MSVC 编译器加/utf-8编译选项),这样整个团队不管怎么提交文件都不会因为编码风格产生乱码。
高DPI的问题在 Qt 6 上已经处理得比较好了,但如果你项目仍在使用 Qt 5,在 Windows 上高分辨率屏幕下界面很模糊,通常需要在main函数里QApplication::setAttribute前设置高 DPI 缩放属性,这个具体参数按你使用的 Qt 版本去查文档就好。
另外,调试器缺失也是新手容易忽略的一环。Kit 选择正确,编译运行都正常,但点击调试按钮(F5)时提示找不到调试器。安装 Qt 时,MinGW 版本会附带 GDB 调试器,基本开箱即用;MSVC 环境则需要确认 Windows SDK 或 Visual Studio 的 Debugger Tools 是否安装。没有调试器你就只能靠编译报错和日志排查问题,难度会高不少。
5.4 几个容易误判的“工程配置”问题
还有几个问题不常提到,但我遇到过不少次,列出来供你参考。
第一个是“改了代码没变化”。排除代码本身没保存的情况,最常见的是你在 Debug 模式下改代码,结果运行的还是旧版本 Release 构建;或者反过来。Qt Creator 的构建套件选择在左下角,运行按钮旁边的配置下拉框里可以切换 Debug/Release。不同配置的构建目录是分开的,所以运行前确认当前选择哪个配置。
第二个是窗口显示后立刻消失。这在Qt Console Application里尤其常见:程序执行完 main 函数就结束了,控制台窗口一闪而过。解决办法是在工程配置里加上CONFIG += console,或者直接在代码里在函数末尾加上等待输入的暂停逻辑。这不是工程创建的问题,而是控制台程序的特性导致。
第三个是.ui文件在代码里找不到控件。新拖入一个控件后,编译通过但代码里访问ui->myButton时报错。原因是ui_mainwindow.h是在构建时由 uic 根据.ui文件内容生成的,如果你拖完控件没有保存.ui文件,或者构建没有重新触发,新控件就不会出现在生成的代码里。先保存,再重新构建,问题就解决了。不要手动去改ui_mainwindow.h,那个文件是自动生成的。
最后说点我自己的实操体会。这些年我新建过很多 Qt 工程,早期总喜欢一把梭,建完工程立刻开始写界面写逻辑,结果每次搭建环境和编译调试都消耗不少时间。后来我养成一个习惯:新工程建完后,先花几分钟把空白窗口跑起来,确认编译、运行、调试三个链路都通,再开始写代码。这个习惯帮我排掉了大量“工程本身有问题”的干扰。
还有一个实用小技巧:给工程起名时尽量带上用途,比如VideoPlayerDemo、SerialPortTool,而不是untitled1、newproject2。Qt Creator 会用工程名生成默认的窗口标题和可执行文件名,名字起得清晰,后面管理和查错都轻松得多。新建工程这件事,看似简单,但把每个选项背后的逻辑弄明白,能给后面省下不少事。