При миграции с Qt5 на Qt6 значительная часть работы — это механическая замена устаревших классов и методов. Ниже приведена таблица наиболее частых соответствий, а также примеры кода «было/стало» для самых проблемных случаев.
Таблица соответствий API
| Qt5 (устаревшее/удалённое) | Qt6 (рекомендуемое) | Комментарий |
|---|---|---|
QRegExp | QRegularExpression | QRegExp доступен через модуль Qt5Compat |
QStringRef | QStringView | Полная замена, более широкий функционал |
QTextCodec | QStringConverter / QStringEncoder | Для перекодирования текста |
qrand(), qsrand() | QRandomGenerator | Современный, потокобезопасный генератор |
QDesktopWidget | QScreen (через QGuiApplication::screens()) | QDesktopWidget удалён |
Qt::AA_EnableHighDpiScaling | Не требуется — включено по умолчанию | High DPI всегда активен в Qt6 |
QApplication::desktop() | QGuiApplication::primaryScreen() | Получение размеров экрана |
qt_qFindChild | QObject::findChild<T>() | Устаревшая внутренняя функция |
QLinkedList | std::list | Контейнер удалён из Qt6 |
QVector | QList (объединён с QVector) | QVector — теперь алиас QList |
QQuickView::rootContext()->setContextProperty | то же, но проверять время инициализации | Поведение порядка инициализации изменилось |
QtQuick.Controls 1.x | QtQuick.Controls 2.x | Controls 1 удалён полностью |
QOpenGLWidget напрямую для 3D-сцен | Qt Quick 3D / RHI-абстракция | Рекомендуется для новых проектов |
QSignalMapper | Лямбды в connect() | Более идиоматичный подход в C++11+ |
qSort() / qStableSort() | std::sort() / std::stable_sort() | Используем STL-алгоритмы напрямую |
QString::SplitBehavior::KeepEmptyParts | Qt::SplitBehaviorFlags::KeepEmptyParts | Изменено пространство имён enum |
Пример: замена QRegExp
// Qt5
#include <QRegExp>
bool isValidEmail(const QString &email) {
QRegExp rx("^[\\w.+-]+@[\\w-]+\\.[a-zA-Z]{2,}$");
return rx.exactMatch(email);
}
// Qt6
#include <QRegularExpression>
bool isValidEmail(const QString &email) {
static const QRegularExpression rx(
"^[\\w.+-]+@[\\w-]+\\.[a-zA-Z]{2,}$");
QRegularExpressionMatch match = rx.match(email);
return match.hasMatch() && match.capturedLength() == email.length();
}
Пример: замена qrand на QRandomGenerator
// Qt5
qsrand(QTime::currentTime().msec());
int value = qrand() % 100;
// Qt6
int value = QRandomGenerator::global()->bounded(100);
QRandomGenerator потокобезопасен и не требует ручной инициализации seed — это и проще, и безопаснее в многопоточном коде.
Пример: замена QSignalMapper на лямбды
// Qt5
QSignalMapper *mapper = new QSignalMapper(this);
connect(button1, &QPushButton::clicked, mapper, [=]{ mapper->map(button1); });
mapper->setMapping(button1, 1);
connect(mapper, &QSignalMapper::mappedInt, this, &MyClass::onButtonClicked);
// Qt6 — лямбда захватывает нужный идентификатор напрямую
connect(button1, &QPushButton::clicked, this, [this]{ onButtonClicked(1); });
connect(button2, &QPushButton::clicked, this, [this]{ onButtonClicked(2); });
Пример: получение информации об экране
// Qt5
QRect screenRect = QApplication::desktop()->screenGeometry();
// Qt6
QRect screenRect = QGuiApplication::primaryScreen()->geometry();
Использование модуля совместимости Qt5Compat
Если переписать всё сразу невозможно (например, в стороннем коде), можно временно подключить модуль совместимости:
find_package(Qt6 REQUIRED COMPONENTS Core5Compat)
target_link_libraries(MyApp PRIVATE Qt6::Core5Compat)
#include <QtCore5Compat/QRegExp> // временное решение, не для нового кода
Подводные камни
- QVector и QList объединены, но семантика QVector (гарантия contiguous storage) сохранена для QList в Qt6 — это упрощает миграцию, но код, рассчитывающий на отдельные оптимизации QVector, может потребовать профилирования.
- enum-классы стали строже типизированными — неявные приведения
int→enumв местах вродеQt::SplitBehaviorтеперь требуют явного указания пространства имён. - QStringRef и QStringView не идентичны по API — у
QStringViewнет некоторых методов вродеtoString()без копирования, проверяйте семантику владения данными. - Не удаляйте
Qt5Compatсразу при миграции крупного проекта — используйте его как промежуточный шаг, переписывая код постепенно, модуль за модулем.
================================================================================