QtJuniorTechnical

Что такое 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 слоем.

Sources

Related topics