[实战笔记] 从 Qt 5.12.9 跨越到 Qt 6.x 完美迁移指南 (Windows + VS)
前言
最近我将一个基于 Qt 5.12.9 (LTS) 开发的老项目(AwsHacker)迁移到了最新的 Qt 6 环境。
作为一个跨越了两个大版本的迁移(Qt 5.12 -> Qt 6),中间的坑非常多:QML 语法从宽松变得严格、QtQuick.Controls 1 被彻底移除、以及 C++ 容器底层实现的重大变更。虽然网上建议先升级到 5.15 过渡,但我最终完成了从老版本到新架构的全面适配。
本文记录了完整的迁移填坑过程,希望能帮助同样还在坚守 Qt 5.12 的朋友们顺利升级。
一、 环境准备
1. 软件安装
- IDE: Visual Studio 2022 / 2026 (推荐安装最新版,配合 Qt Visual Studio Tools)。
- Qt 版本: 建议安装最新的 Qt 6 LTS (如 6.5 或 6.8)。
- 编译器: MSVC 2019 64-bit 或 MSVC 2022 64-bit。
2. 关键组件 (必装!)
在安装 Qt 6 时,务必在 Additional Libraries 中勾选:
- ✅ Qt 5 Compatibility Module (Qt 5 兼容模块)
注意 :Qt 6 移除的大量旧类(如
QTextCodec,QRegExp等)都移到了这个模块里。如果不装,从 5.12 迁移过来的代码会大面积报错。
安装qt5.15.2需要选择Archive才能看到

二、 项目配置 (.pro) 与构建系统
1. 修改 .pro 文件
Qt 5.12 时期很多默认开启的模块在 Qt 6 需要手动引入,且 C++ 标准必须提升。
qmake
# 1. 强制启用 C++17 (Qt 6 硬性要求,5.12 默认通常是 C++11/14)
CONFIG += c++17
# 2. 加载 Qt 5 兼容模块
greaterThan(QT_MAJOR_VERSION, 5): QT += core5compat
# 3. 显式引入 Quick Controls 2 (如果你用了 QQuickStyle)
QT += quickcontrols2
2. 解决"构建路径"报错
现象 :编译时提示 dependent '..\..\Qt\...\QObject' does not exist。
原因 :Qt Creator 默认的构建目录层级过深,qmake 相对路径计算溢出。
解决:
- 彻底删除 项目目录下的
.pro.user文件和旧build文件夹。 - 在 Qt Creator 的"项目 -> 构建设置"中,将构建目录修改为与源码同级 (Shadow Build):
../build-%{Project:Name}-%{Kit:FileSystemName}-%{BuildConfig:Name}
- 重新执行 qmake。
三、 C++ 代码修正 (编译报错)
1. 容器类的 const 限制 (QList/QVector)
背景 :Qt 5.12 的 QList 是指针数组,对元素要求不严。Qt 6 的 QList 变成了 QVector,要求元素必须可赋值 。
报错 :attempting to reference a deleted function (operator=)。
❌ 旧代码 (Qt 5.12 能跑):
cpp
struct VersionData {
const QString key = "version"; // const 成员导致结构体无法赋值
QString value;
};
✅ 新代码 (Qt 6):
cpp
struct VersionData {
// 方案 A: 去掉 const,变回普通变量
QString value;
// 方案 B: 提到类级别,改为静态常量
static inline const QString key = "version";
};
2. 网络模块变动
从 5.12 到 6,QNetworkAccessManager 变化巨大:
- 重定向策略 :
- 旧:
req.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); - 新:
req.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::NoLessSafeRedirectPolicy);
- 旧:
- 信号重命名 :
- 旧:
QNetworkReply::error(存在重载歧义) - 新:
QNetworkReply::errorOccurred
- 旧:
3. 字符串编码安全
报错 :QByteArray::append(QString) 报错。
解决:Qt 6 移除了隐式转换,必须显式指定编码(通常用 UTF-8):
cpp
byteArray.append(str.toUtf8());
四、 QML 语法与模块适配 (重灾区)
1. 彻底移除 QtQuick.Controls 1
Qt 5.12 时期很多人还在用 Controls 1 (TreeView, TableViewColumn),这些在 Qt 6 完全不存在了。
- 修改 Import :把
import QtQuick.Controls 1.4改为import QtQuick.Controls(即 Controls 2)。 - 重写 TreeView :必须使用 Qt 6 新增的
TreeView+TreeViewDelegate+HorizontalHeaderView进行完全重写。
2. 彻底移除 QtGraphicalEffects
- 旧:
import QtGraphicalEffects 1.0 - 新:
import Qt5Compat.GraphicalEffects(需要安装兼容模块)。
3. Connections 语法变更
Qt 5.12 允许在 Connections 中直接使用信号参数,Qt 6 必须显式写出。
❌ 旧代码 (5.12):
qml
Connections {
target: backend
onDataLoaded: console.log(data) // 隐式参数,Qt 6 报错 "data is not defined"
}
✅ 新代码 (Qt 6):
qml
Connections {
target: backend
// 必须加 function,且括号里必须写参数名!
function onDataLoaded(data) {
console.log(data)
}
}
五、 UI 样式问题 (Windows)
现象 :5.12 下正常的自定义按钮,在 Qt 6 Windows 环境下报错 The current style does not support customization。
原因:Qt 6 在 Windows 下默认使用原生样式,强制接管绘制,禁止修改背景。
解决方案 :
在 main.cpp 中强制切换回基础样式,还原 Qt 5 的自由度:
cpp
#include <QQuickStyle>
int main(...) {
QQuickStyle::setStyle("Basic"); // 类似于 Qt 5 的默认行为
// ...
}
六、 总结
从 Qt 5.12.9 到 Qt 6 的跨度虽然大,但只要抓住了 "C++容器去const化" 、"QML 显式函数化" 以及 "模块新旧替换" 这几个核心点,迁移是可以平滑进行的。
现在的 AwsHacker 项目已经在 Qt 6 + VS 2026 环境下流畅运行,渲染性能相比 5.12 有了显著提升。希望这篇笔记能帮大家避开同样的坑!