QML#

QML (Qt Modeling Language) — это декларативный язык, основанный на JavaScript, который позволяет легко описывать интерфейсы и их поведение. В рамках Qt возможно использовать использовать функционал C++ в сочетании с продвинутым GUI, построенном на QML.

Основные пакеты#

Пакет

Версия

Репозиторий

Описание

qtdeclarative5-dev

5.15.8+dfsg-3astra1+b1

extended

Библиотеки Qt для QML

gcc

4:12.2.0-3+b1

extended

GNU C компилятор

g++

4:12.2.0-3+b1

extended

GNU C++ компилятор

cmake

3.25.1-1+b3

extended

Кроссплатформенное средство автоматизации сборки ПО из исходного кода

Дополнительные пакеты#

Пакет

Версия

Репозиторий

Описание

qtcreator

7.0.2-2astra2+b1

extended

IDE для разработки приложений Qt

gdb

13.1-3+b2

extended

GNU отладчик

Установка QML#

Перед началом разработки необходимо установить Qt с поддержкой QML и необходимые зависимости (минимальный набор пакетов):

sudo apt install gcc g++ cmake qtdeclarative5-dev

Установка инструментов разработки:

Для разработки возможно установить IDE Qt Creator, а также отладчик gdb:

sudo apt install qtcreator gdb

Создание QML-приложения#

Структура проекта#

  • пример структуры проекта:

project/
│
├── main.cpp         # Основной файл приложения на C++
└── qml.qrc          # Файл ресурсов
   └──/              # Корень файла ресурсов
      └──main.qml    # QML-файл с описанием интерфейса

Пример проекта с QML и C++#

Рассмотрим пример создания простого приложения на C++ с использованием QML. Оно отображает окно с двумя кнопками и текстовым полем.

  • Одна кнопка изменяет текст при нажатии (в данном случае один QML-объект воздействует на другой QML-объект).

  • Вторая кнопка вызывает выполнение кода C++, расположенного в main.cpp

Приступим к созданию приложения.

  1. Создайте файл main.qml:

import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15

ApplicationWindow {
    visible: true
    width: 400
    height: 300
    title: "QML Пример"

    Column {
        anchors.centerIn: parent
        spacing: 10

        Button {
            id: buttonChangeText
            text: "Изменить текст"
            onClicked: label.text = "Вы нажали кнопку!" // обращение по id QML-объекта
        }

        Button {
            id: buttonShowMessage
            text: "Показать сообщение"
            onClicked: backend.showMessage() // обращение к слоту объекта C++, зарегистрированному в контексте QML (см. main.cpp)
        }

        Label {
            id: label
            text: "Привет, мир!"
        }
    }
}
  1. Создайте файл ресурсов qml.qrc, затем добавьте в его корень файл main.qml.

Его содержимое в текстовом виде:

<RCC>
    <qresource prefix="/">
        <file>main.qml</file>
    </qresource>
</RCC>
  1. Создайте файл main.cpp:

#include <QApplication>
#include <QMessageBox>
#include <QQmlApplicationEngine>
#include <QQmlContext>

// класс-приёмник, который будет принимать сигнал от QML
class Backend : public QObject {
  Q_OBJECT
 public:
  explicit Backend(QObject *parent = nullptr) : QObject(parent) {}

 public slots:
  void showMessage() {
    QMessageBox::information(nullptr, "Сообщение", "Кнопка нажата!");
  }
};

int main(int argc, char *argv[]) {
  // создаём приложение (QApplication вместо QGuiApplication, т.к. используется QMessageBox)
  QApplication app(argc, argv);

  // создаём движок QML
  QQmlApplicationEngine engine;

  // создаём "приёмник"
  Backend backend(&app);

  // регистрируем "приёмник" в контексте QML, чтобы можно было из QML обратиться к его слотам
  engine.rootContext()->setContextProperty("backend", &backend);

  // получаем URL QML-файла из ресурсов
  const QUrl url(QStringLiteral("qrc:/main.qml"));

  // опционально: проверка работоспособности файла QML по заданному URL
  QObject::connect(
      &engine, &QQmlApplicationEngine::objectCreated, &app,
      [url](QObject *obj, const QUrl &objUrl) {
        if (!obj && url == objUrl) {
          qWarning() << "Invalid QML file: QObject could not be "
                        "created.\nURL:"
                     << url;
          QCoreApplication::exit(-1);
        }
      },
      Qt::QueuedConnection);

  // загрузка QML-файла
  engine.load(url);

  // запуск приложения
  return app.exec();
}

#include "main.moc" // иначе AutoMoc error при компиляции
  1. Создайте файл CMakeLists.txt:

cmake_minimum_required(VERSION 3.14)

project(qt-quick-test VERSION 0.1 LANGUAGES CXX)

set(CMAKE_INCLUDE_CURRENT_DIR ON)

set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core Quick Widgets)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Quick Widgets)

set(PROJECT_SOURCES
        main.cpp
        qml.qrc
)

add_executable(qt-quick-test
  ${PROJECT_SOURCES}
)

target_compile_definitions(qt-quick-test
  PRIVATE $<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:QT_QML_DEBUG>)
target_link_libraries(qt-quick-test PRIVATE
  Qt${QT_VERSION_MAJOR}::Core
  Qt${QT_VERSION_MAJOR}::Quick
  Qt${QT_VERSION_MAJOR}::Widgets)

Объяснение кода#

Пункт 1#

QML-часть (main.qml)

ApplicationWindow: Основное окно приложения.

Column: разметка окна, располагает вложенные элементы в колонну.

Label: Текстовый элемент, который отображает сообщение.

Button: Кнопка, при нажатии на которую выполняется действие onClicked.

onClicked: возможно выполнение кода без выхода за пределы QML ( см. buttonChangeText в main.qml), а также кода C++ (для этого нужно зарегистрировать QObject в контексте QML - см. main.cpp - а затем обратиться к его слоту - см. buttonShowMessage в main.qml)

Пункт 2#

Ресурсы .qrc

Файл ресурсов qml.qrc нужен, чтобы избежать проблем с относительными путями при загрузки QML-файлов: поиск QML-файлов осуществляется в момент исполнения программы в текущей рабочей директории, которая может не совпадать с директорией с исходным кодом.

Пункт 3#

Cpp-часть (main.cpp)

  • создаем приложение;

  • создаём класс, принимающий сигнал от QML, и регистрируем его в контексте QML;

  • загружаем QML-файл;

  • запускаем приложение.

Подробные комментарии в коде.

Пункт 4#

CMakeLists.txt нужен для удобства сборки с помощью CMake.

Компиляция и запуск:#

Уже описана в разделе «Компиляция и запуск» Qt5.

Отладка#

Отладка cpp-кода уже описана в разделе «Отладка» Qt5.

Отладка QML#

  • Включить отладку QML при сборке:

Проекты -> Сборка и запуск -> Сборка -> Отладка и профилирование QML: выбрать Enable

  • Пересобрать проект:
    • Для проекта CMake: в том же окне нажать кнопку «Run CMake», затем скомпилировать проект.

    • Для проекта QMake: согласиться на перекомпиляцию проекта.

  • Поставить галку в чекбокс «Включить QML», если не стоит:

Проекты -> Сборка и запуск -> Запуск -> Настройки отладчика -> Включить QML

  • Запустить отладку из QT Creator.

Процесс отладки аналогичен отладке Cpp-приложений в Qt Creator.

Упаковка в установочный файл#

Уже описана в разделе «Упаковка в установочный файл» Qt5.