Переход с Qt5 на Qt6 — это не просто смена номера версии в файле сборки. Qt6 принёс изменения в систему сборки (переход на CMake как основной инструмент), переработку модулей (QtQuick, Qt Multimedia, Qt Positioning), отказ от ряда устаревших классов и переход на C++17 как минимальный стандарт. Для крупных проектов миграция может занять от нескольких дней до нескольких недель, поэтому важно подойти к ней системно.
Зачем мигрировать
Qt5 уже не получает новых функций, а коммерческая поддержка старых версий ограничена по времени. Qt6 даёт более быстрый рендеринг QML (новый RHI — Rendering Hardware Interface), улучшенную поддержку Unicode (QString теперь хранит UTF-8 внутри), а также активную разработку модулей вроде Qt Quick 3D и Qt Multimedia.
Чек-лист миграции
- Обновите систему сборки. Если проект использует qmake — рассмотрите переход на CMake, так как именно CMake является приоритетной системой сборки в Qt6.
- Проверьте минимальный стандарт C++. Qt6 требует C++17.
- Замените устаревшие API (см. отдельную статью с таблицей соответствий).
- Проверьте используемые модули. Некоторые модули были переименованы или объединены (например, Qt Quick Controls 1 удалён полностью).
- Пересоберите все плагины и сторонние библиотеки под Qt6 — бинарная совместимость с Qt5 отсутствует.
- Проверьте сериализацию данных, если используется QDataStream — формат версии потока изменился.
- Прогоните автотесты на каждом этапе миграции.
Пример: обновление CMakeLists.txt
cmake_minimum_required(VERSION 3.16)
project(MyApp LANGUACHES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
# Поддержка одновременно Qt5 и Qt6 на время миграции
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core Widgets)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Widgets)
add_executable(MyApp main.cpp mainwindow.cpp)
target_link_libraries(MyApp PRIVATE
Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Widgets
)
if (QT_VERSION_MAJOR EQUAL 6)
qt_finalize_executable(MyApp)
endif()
Такой приём с find_package(QT NAMES Qt6 Qt5 ...) позволяет одним CMakeLists.txt собирать проект и под Qt5, и под Qt6 на переходный период, что облегчает постепенную миграцию.
Типичные проблемы при компиляции
Проблема 1. QStringRef удалён.
// Qt5
QStringRef ref = str.midRef(2, 5);
// Qt6 — используем QStringView
QStringView ref = QStringView(str).mid(2, 5);
Проблема 2. Неявные преобразования QString → bool/int удалены.
В Qt6 ужесточена работа с неявными преобразованиями. Код вида if (myQString) больше не компилируется — нужно явно писать if (!myQString.isEmpty()).
Проблема 3. Изменение поведения QRegExp.
Класс QRegExp помечен устаревшим уже в Qt5, но в Qt6 он перенесён в отдельный модуль Qt5Compat. Рекомендуется переход на QRegularExpression:
// Было
QRegExp rx("\\d+");
if (rx.indexIn(text) != -1) { ... }
// Стало
QRegularExpression rx("\\d+");
QRegularExpressionMatch match = rx.match(text);
if (match.hasMatch()) { ... }
Проблема 4. QML import-версии.
В QML-файлах теперь не обязательно указывать минорную версию модуля:
// Qt5
import QtQuick 2.15
import QtQuick.Controls 2.15
// Qt6 — минорную версию можно не указывать
import QtQuick
import QtQuick.Controls
Подводные камни
- Qt5Compat. Многие устаревшие классы (QTextCodec, QRegExp) доступны через дополнительный модуль
Qt5Compat, который нужно подключать явно:find_package(Qt6 REQUIRED COMPONENTS Core5Compat). - Изменение порядка инициализации QML-движка может привести к тому, что синглтоны, зарегистрированные через
qmlRegisterSingletonType, инициализируются позже, чем в Qt5. - Изменения в системе плагинов. Плагины (image format, sqldrivers) должны быть пересобраны заново — старые .dll/.so от Qt5 не подходят.
- Различия в обработке High DPI. В Qt6 масштабирование High DPI включено по умолчанию и не настраивается через
Qt::AA_EnableHighDpiScaling(атрибут удалён, так как поведение стало стандартным).
Совет: мигрируйте поэтапно
Не пытайтесь переписать весь проект за один присест. Разделите миграцию на этапы: сначала система сборки, затем устранение предупреждений компилятора, затем замена устаревших API, и только потом — полный переход на новые возможности Qt6 (например, Qt Quick 3D вместо самописного OpenGL-рендеринга). На каждом этапе прогоняйте полный набор тестов, чтобы локализовать регрессии.
================================================================================