Регистрация типов QML позволяет разработчику управлять жизненным циклом объекта C++ из среды QML. Этого невозможно достичь с помощью свойств контекста. В подобном случае объект C++ не является частью глобального контекста. Тем не менее, все типы необходимо сначала зарегистрировать.
Чтобы в коде QML использовать данные, функции или прочий функционал из кода C++, этот функционал должен быть оформлен в клас, скоторый является производным от QObject. Такое взаимодействие будет возможно, так как все типы объектов QML реализованы в виде классов, производных от QObject.
Итак, сначала добавим в проект новый класс C++. Если мы работаем в Qt Creator, то в структуре проекта нажмем на узел Source Files и в контекстном меню выберем Add New...
В окне добавления нового элемента выберем C++ Class
На следующем шаге укажем для добавляемого класса какое-нибудь именя, например, в моем случае это "Custom"
По умолчанию в проект будут добавлены два файла - файл с функционалом и заголовочный файл класса. В моем случае это "custom.cpp" и "custom.h".
В заголовочном файле custom.h пропишем следующий код:
#ifndef CUSTOM_H #define CUSTOM_H #include <QObject> class Custom : public QObject { Q_OBJECT public: explicit Custom(QObject *parent = nullptr); Q_INVOKABLE int getTextSize() {return textSize; } Q_INVOKABLE QString getTextContent() {return textContent; } private: int textSize {18}; QString textContent {"Hello World"}; }; #endif // CUSTOM_H
Прежде всего нам надо унаследовать класс от QObject
class Custom : public QObject { Q_OBJECT
Внутри класса с помощью встроенного макроса Q_OBJECT
вставляем в класс весь необходимый функционал родительского класса.
Определяем конструктор, который в качестве может принимать через параметр типа QObject родительский контейнер
explicit Custom(QObject *parent = nullptr);
Чтобы сделать доступными для QML методы класса определяются с флагом Q_INVOKABLE. В данном случае у нас два таких метода, который просто возвращают значения приватных полей:
Q_INVOKABLE int getTextSize() {return textSize; } Q_INVOKABLE QString getTextContent() {return textContent; } private: int textSize {18}; QString textContent {"Hello World"};
Метод getTextSize()
возвращает целочисленное значение, а getTextContent()
- строку в виде встроенного типа QString.
Далее в файле custom.cpp пропишем реализацию пустого конструктора
#include "custom.h" Custom::Custom(QObject *parent) : QObject{parent} {}
Теперь для использования в QML этот тип надо зарегистрировать в главном файле программы main.cpp:
#include <QGuiApplication> #include <QQmlApplicationEngine> #include "custom.h" // подключаем определение нашего типа int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); QQmlApplicationEngine engine; // регистрация типа qmlRegisterType<Custom>("custom", 1, 0,"Custom"); const QUrl url("qrc:/path/main.qml"); engine.load(url); return app.exec(); }
Здесь с помощью функции qmlRegisterType() регистрируется наш компонент Custom. Эта функция имеет следующее определение:
template<typename T> int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const char *qmlName);
Эта функция-шаблон принимает следующие параметры:
uri
- строка-идентификатор ресурса, по которой его можно подключить в QML
versionMajor
- старшая версия компонента
versionMinor
- младшая версия компонента
qmlName
- строка с именем компонента, по которому он будет использоваться в QML
В данном случае класс Custom будет доступен в QML по имени "Custom", а для подключения будет применяться адрес "custom".
Теперь применим этот компонент в main.qml:
import QtQuick import custom // подключаем компонент Custom Window { width: 250 height: 200 visible: true title: "METANIT.COM" Custom{ // Определяем объект Custom id:customObj // назначаем его идентификатор } Text { anchors.centerIn: parent text: customObj.getTextContent() // обращаемся к методам font.pixelSize: customObj.getTextSize() // объекта Custom font.family: "Verdana" } }
Поскольку для компонента Custom установлен uri "custom", то по этому uri подключаем его в файл qml. Далее мы можем создавать объекты Custom. В данном случае создается один объект, у которого просто устанавливается идентификатор customObj. После этого по данному идентифкатору мы можем обращаться к функциональности объекта. В частности, обращаемся к его методам для установки свойств объекта Text. Результат работы приложения: