Qt6 — первое крупное обновление основной версии фреймворка за много лет. В отличие от перехода Qt4 → Qt5, который был довольно болезненным, Qt6 спроектирован так, чтобы упростить поддержку кода, работающего одновременно со старой и новой версией. Разберём ключевые изменения, которые реально влияют на повседневную разработку.
1. CMake как основная система сборки
qmake продолжает поддерживаться, но все новые возможности (модульность, генерация ресурсов, deployment-инструменты) появляются прежде всего в CMake-инфраструктуре. Пример минимального проекта:
cmake_minimum_required(VERSION 3.16)
project(HelloQt6 VERSION 1.0 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_AUTOMOC ON)
find_package(Qt6 REQUIRED COMPONENTS Widgets)
qt_standard_project_setup()
qt_add_executable(HelloQt6 main.cpp)
target_link_libraries(HelloQt6 PRIVATE Qt6::Widgets)
Функция qt_standard_project_setup() — новинка Qt6, она автоматически настраивает AUTOMOC, AUTORCC, стандарт каталогов и др.
2. Изменение модели хранения QString
Внутри QString теперь хранятся данные в UTF-16, но добавлен полноценный класс QStringView для работы без копирования, а также улучшена поддержка UTF-8 через QUtf8StringView. Это особенно важно при работе с большими текстовыми данными:
void processLine(QStringView line) {
if (line.startsWith(u"//"))
return; // комментарий, пропускаем без копирования строки
qDebug() << "Line:" << line;
}
QString text = "// comment\nreal data";
for (const auto &line : QStringView(text).split(u'\n'))
processLine(line);
3. Новый рендеринг QML — RHI (Rendering Hardware Interface)
В Qt5 QtQuick жёстко завязан на OpenGL. В Qt6 добавлен слой абстракции RHI, который позволяет выбирать backend: Direct3D, Vulkan, Metal или OpenGL — в зависимости от платформы.
// main.qml — поведение не меняется, но под капотом
// рендерер может работать через Direct3D 11 на Windows
import QtQuick
import QtQuick.Window
Window {
visible: true
width: 640
height: 480
Rectangle {
anchors.fill: parent
color: "lightblue"
}
}
Backend можно явно задать переменной окружения:
set QSG_RHI_BACKEND=d3d11
4. Удаление и реорганизация модулей
Qt Quick Controls 1— полностью удалён, остался толькоQt Quick Controls 2(импортируется просто какQtQuick.Controls).QtWebEngineтеперь требует отдельного внимания к версиям Chromium.Qt Multimediaпереписан с нуля, API существенно отличается от Qt5-версии.- Появился
Qt Quick 3Dдля декларативного 3D на QML.
5. Строгая типизация в QML
В Qt6 появилась возможность компилировать QML «статически» (qmlcachegen / qmltc), что требует более строгих типов в QML-коде:
import QtQuick
Item {
// Явное указание типа свойства упрощает статическую компиляцию
property int counter: 0
property string label: "Count: " + counter
Timer {
interval: 1000; running: true; repeat: true
onTriggered: counter++
}
}
6. Изменение базовых типов
qreal стал везде типом double (на 32-битных платформах раньше это мог быть float), что устраняет ряд проблем с точностью на ARM-платформах.
7. Поддержка C++17 как минимум
Код, использующий Q_FOREACH, по-прежнему работает, но рекомендуется переходить на range-based for и структуры C++17:
// современный стиль с std::optional вместо проверки isValid()
std::optional<QString> findUser(int id) {
if (id == 42)
return QString("Alice");
return std::nullopt;
}
if (auto user = findUser(42)) {
qDebug() << "Found:" << *user;
}
Подводные камни
- Старые скомпилированные
.qmlc-кэши и плагины не совместимы между Qt5 и Qt6 — необходима полная пересборка. - Сторонние библиотеки (например, QZXing, qtkeychain) нужно проверять на поддержку Qt6 — не все обновились одновременно.
- В новых дистрибутивах Linux часто присутствует только Qt6, без Qt5 — тестируйте deployment заранее.
Совет
Перед началом активной разработки на Qt6 проверьте, что все используемые сторонние библиотеки и плагины имеют актуальные релизы под Qt6. Это сэкономит время на этапе интеграции значительно больше, чем любые отличия в самом коде Qt-приложения.
================================================================================