CMake + QML 环境配置
101. Qt 项目 CMake 集成 QML 环境配置
日期: 2026-05-20 关联开发任务: 阶段 1 任务 1.1 项目初始化 关联设计文档: 001.概要设计文档、009.开发规范文档
一、问题/需求描述
Qt Creator 6.x 新建项目默认生成 QWidget + QMainWindow + .ui 表单 模板。但概要设计文档 [001:行15] 明确要求 UI 层使用 QML(Qt Quick)。需要在不引入 qmake 的前提下,用纯 CMake 将项目切换到 QML 技术栈,并保留跨平台编译能力(Windows/macOS/Linux)。
附带问题:项目启动时误以为 QML 需要 qmake 构建系统——这是 Qt 历史资料最常见的误导。
二、思路
- 澄清误解:QML 是 Qt 的运行时模块(
Qt6::Quick),通过find_package+target_link_libraries引入,与Qt6::Widgets平级,不需要也不应该用 qmake - CMake 改造:在现有 CMakeLists.txt 的
find_package中增加Quick、QuickControls2组件;target_link_libraries增加对应库 - 入口改造:
main.cpp从QApplication+QMainWindow::show()改为QQmlApplicationEngine加载 QML 文件 - 资源管理:创建
.qrc文件索引 QML 文件和静态资源,通过qrc:/前缀引用 - 清理遗留:删除
mainwindow.h、mainwindow.cpp、mainwindow.ui——它们是纯 QWidget 代码,与 QML 方向互斥
三、逻辑推导
QML 加载链
main.cpp
↓ QApplication app(argc, argv)
↓ QQmlApplicationEngine engine
↓ engine.load("qrc:/qml/main.qml")
↓ 解析 .qrc → 定位 src/ui/qml/main.qml
↓ Qt Quick 运行时渲染 ApplicationWindow
CMake 模块依赖链
SmartDietManager
├── Qt6::Widgets ← 保留(未来系统托盘/文件对话框)
├── Qt6::Quick ← QML 运行时引擎
├── Qt6::QuickControls2 ← ApplicationWindow / Button 等控件
├── Qt6::Sql ← 预置(1.3 数据库用)
├── Qt6::Network ← 预置(HTTP REST 用)
└── Qt6::WebSockets ← 预置(阶段 8 实时同步用)
四、实施方案
4.1 CMakeLists.txt 核心改动
# 新增 Quick QuickControls2 Sql Network WebSockets 模块
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS
Widgets Quick QuickControls2 Sql Network WebSockets LinguistTools)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS
Widgets Quick QuickControls2 Sql Network WebSockets LinguistTools)
# 移除 Widget 源文件,加入 QML 资源文件
set(PROJECT_SOURCES
src/app/main.cpp
resources/translations/SmartDietManager_zh_CN.ts
resources.qrc # ← 新增
)
# 链接所有模块
target_link_libraries(SmartDietManager PRIVATE
Qt${QT_VERSION_MAJOR}::Widgets
Qt${QT_VERSION_MAJOR}::Quick
Qt${QT_VERSION_MAJOR}::QuickControls2
Qt${QT_VERSION_MAJOR}::Sql
Qt${QT_VERSION_MAJOR}::Network
Qt${QT_VERSION_MAJOR}::WebSockets
)
4.2 resources.qrc(新建)
<RCC>
<qresource prefix="/qml">
<file alias="main.qml">src/ui/qml/main.qml</file>
</qresource>
</RCC>
4.3 main.cpp(重写)
#include <QApplication>
#include <QQmlApplicationEngine>
#include <QLocale>
#include <QTranslator>
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
QTranslator translator;
const QStringList uiLanguages = QLocale::system().uiLanguages();
for (const QString &locale : uiLanguages) {
const QString baseName = "SmartDietManager_" + QLocale(locale).name();
if (translator.load(":/i18n/" + baseName)) {
app.installTranslator(&translator);
break;
}
}
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/qml/main.qml")));
if (engine.rootObjects().isEmpty()) return -1;
return app.exec();
}
4.4 main.qml(新建)
import QtQuick
import QtQuick.Controls
import QtQuick.Window
ApplicationWindow {
id: root
width: 800
height: 600
visible: true
title: "SmartDietManager"
color: "#F5F5F5"
Text {
anchors.centerIn: parent
text: "🥗 SmartDietManager"
font.pixelSize: 24
color: "#333333"
}
}
4.5 删除文件
src/ui/views/mainwindow.h ← QMainWindow 声明
src/ui/views/mainwindow.cpp ← QMainWindow 实现
src/ui/views/mainwindow.ui ← Qt Designer 表单
五、可行性分析
| 维度 | 评估 |
|---|---|
| Qt 兼容性 | QQmlApplicationEngine 自 Qt 5.1 起可用,Qt 6.x 完全支持 |
| CMake 兼容性 | CMAKE_AUTORCC ON 自动处理 .qrc 编译,无需手写命令 |
| 跨平台 | QML 在 Windows/macOS/Linux 均原生渲染,无需平台适配代码 |
| 与现有代码冲突 | 删除的 Widget 文件无其他引用,安全移除 |
| Qt::Widgets 保留 | 为后续 QSystemTrayIcon、QFileDialog 预留接口 |
六、验证
| 验证项 | 方法 | 结果 |
|---|---|---|
| CMake 配置无报错 | cmake -S . -B build -DCMAKE_PREFIX_PATH=... | ✅ |
| MOC/QRC/RCC 自动处理 | 检查 build 目录生成文件 | ✅ |
| 编译零错误零警告 | cmake --build build | ✅ |
| QML 窗口可启动 | Qt Creator 运行验证(用户确认) | ✅ |
| 无 qmake 依赖 | 项目中不存在 .pro / .pri 文件 | ✅ |