Что такое Qt widgets и чем они отличаются от компонентов QML/Qt Quick?
Qt Widgets — C++-объекты с нативным рендерингом через QPainter/QStyle, подходят для desktop-форм. QML-компоненты — декларативные .qml-файлы с GPU-рендерингом через Scene Graph, реактивными биндингами и встроенными анимациями.
Qt Widgets
Qt Widgets — классический C++-API для создания настольных GUI. Виджеты (QPushButton, QLabel, QTableView и ~150 других) — это объекты C++, напрямую управляющие отрисовкой через QPainter и нативные платформенные стили (QStyle). Макет задаётся через QHBoxLayout, QGridLayout и т.д.
// Widgets: всё в C++
QPushButton *btn = new QPushButton("Нажми меня", this);
QVBoxLayout *layout = new QVBoxLayout(this);
layout->addWidget(btn);
connect(btn, &QPushButton::clicked, this, &MyWindow::onClicked);
QML-компоненты (Qt Quick)
QML — декларативный язык разметки (JSON-подобный синтаксис + JavaScript). Компоненты описывают что отображать и как анимировать, а не как рисовать. Рендеринг через Qt Quick Scene Graph (OpenGL/Vulkan/Metal/Software). Каждый файл .qml — повторно используемый компонент.
// Button.qml
import QtQuick 2.15
import QtQuick.Controls 2.15
Button {
id: root
text: "Нажми меня"
width: 120; height: 40
background: Rectangle {
color: root.pressed ? "#0057b8" : "#005fcc"
radius: 6
}
onClicked: console.log("clicked")
}
Ключевые отличия
- Язык: Widgets — C++; QML — декларативный QML + JS.
- Рендеринг: Widgets — через QPainter/QStyle (нативный вид ОС); QML — через Scene Graph (GPU, аппаратное ускорение).
- Анимации: В Widgets — ручной код или QPropertyAnimation; в QML — встроенный
Behavior on,Transition,SequentialAnimation. - Применимость: Widgets — сложные desktop-формы, таблицы, MDI-приложения; QML — мобильные приложения, встроенные системы, кастомный дизайн.
- Привязки данных: В QML — реактивные биндинги (
width: parent.width / 2); в Widgets — сигналы/слоты вручную. - Переиспользование: Компонент QML = файл .qml, инстанцируется через имя файла; виджет = C++-класс.
Когда что выбирать
- Widgets: нужны нативный вид ОС, сложные таблицы (
QTableView+ model/view), экосистема Qt Designer. - QML: кастомный дизайн, плавные анимации, мобильная / embedded-платформа, командная работа дизайнер + разработчик.
Подводные камни
- Смешивать Widgets и QML в одном окне сложнее:
QQuickWidgetдобавляет накладные расходы и ограничения (нет прозрачности по умолчанию). - QML-компоненты не получают нативный стиль ОС автоматически — нужен
QQuickStyle::setStyle("Material")или собственный стиль. - В QML биндинги легко сломать присваиванием:
width = 100(JS) разрывает декларативный биндингwidth: parent.width. - Виджеты не поддерживают GPU-анимации так же плавно — при высоких требованиях к FPS QML предпочтительнее.
- В QML нет встроенной
QTableView-подобной виртуализации для очень больших списков безListView+cacheBuffer. - Файлы .qml компилируются в байт-код при
qt_add_qml_module— забыв добавить файл в CMake, получите runtime-ошибку вместо ошибки компиляции. - Widgets-приложения не масштабируются на HiDPI автоматически до Qt 5.6+ — нужен
AA_EnableHighDpiScaling. - QML-компоненты — не C++-классы; нельзя напрямую вызвать метод без
Q_INVOKABLEили сигнала.
Common mistakes
- Объяснять Qt Widgets и QML components только по синтаксису, без жизненного цикла и стоимости.
- Игнорировать ошибки, null/empty состояния, порядок инициализации или режим сборки.
- Давать пример, который работает в демо, но ломается при изменении владельца ресурса.
- Смешивать signals/slots с generic callbacks и забывать про thread affinity.
What the interviewer is testing
- Кандидат формулирует точную модель для Qt Widgets и QML components, а не только определение.
- Пример компилируем, безопасен по lifetime и соответствует версии технологии.
- Названы trade-off, ограничения и диагностируемые симптомы ошибки.
- Понимает границу между C++ кодом, runtime/framework metadata и editor/UI слоем.