[实战笔记] 从 Qt 5.12.9 跨越到 Qt 6.x 完美迁移指南 (Windows + VS)

实战笔记 从 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 相对路径计算溢出。
解决

  1. 彻底删除 项目目录下的 .pro.user 文件和旧 build 文件夹。
  2. 在 Qt Creator 的"项目 -> 构建设置"中,将构建目录修改为与源码同级 (Shadow Build):
    • ../build-%{Project:Name}-%{Kit:FileSystemName}-%{BuildConfig:Name}
  3. 重新执行 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.9Qt 6 的跨度虽然大,但只要抓住了 "C++容器去const化""QML 显式函数化" 以及 "模块新旧替换" 这几个核心点,迁移是可以平滑进行的。

现在的 AwsHacker 项目已经在 Qt 6 + VS 2026 环境下流畅运行,渲染性能相比 5.12 有了显著提升。希望这篇笔记能帮大家避开同样的坑!

相关推荐
用户805533698032 天前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
xcyxiner2 天前
DicomViewer (vcpkg Windows和ubuntu编译)7
qt
Quz7 天前
QML Hello World 入门示例
qt
xcyxiner10 天前
DicomViewer (dcmtk读取dcm文件)5
qt
xcyxiner10 天前
DicomViewer (后台线程处理文件)4
qt
xcyxiner11 天前
DicomViewer (添加模型类)3
qt
xcyxiner11 天前
DicomViewer (目录调整) 2
qt
xcyxiner12 天前
dcmtk vtk vtk-dicom(gdcm) 编译(debug) v2
qt
qq_3692243313 天前
Windows全系通用!ntdll.dll文件丢失、报错、闪退问题的完整排查与修复教程
windows·dll·dll修复·dll丢失·dll错误
桥田智能13 天前
桥田智能 QT-650S:面向白车身焊装的 800kg 重载快换解决方案
开发语言·qt·系统架构