mafulechkaMarch 26, 2020, 5:18 a.m.

Регистрация типа QML в Qt 5.15

Qt 5.15 предоставляет значительно улучшенный способ представления типов C++ для QML. Теперь вы можете указать имя и версию вашего модуля в центральном месте, и больше не нужно указывать минорные версии или ревизии. Кроме того, специфика регистрации типа QML теперь может быть заявлена в объявлении класса C++.

До сих пор распространенным способом обеспечения доступности типов C++ в QML было использование функций регистрации, представленных в заголовке qqml.h header: qmlRegisterType(), qmlRegisterSingletonType(), qmlRegisterUncreatableType() и т. д. У этого подхода есть свои недостатки:

вы всегда должны держать свои регистрации типов в синхронизации с фактическими типами. Это особенно утомительно, если вы используете ревизии, чтобы сделать свойства доступными в разных версиях импорта. Даже если это не так, тот факт, что вам нужно указывать регистрацию отдельно от типа, является обременительным, поскольку вы можете легко потерять учет того, как вы регистрировали, какие типы в какие модули.

Кроме того, поскольку вы регистрируете свои типы процедурно, любой инструмент QML не может автоматически определить, какие типы доступны в каком импорте. Qt Creator действительно имеет некоторые эвристические методы, которые пытаются обнаружить общие шаблоны регистрации в коде C++, но это является неполным. Выяснение того, будет ли программа выполнять определенную регистрацию, эквивалентно решению проблемы остановки. Более простые инструменты, такие как qmllint или qmlformat, не имеют информации о коде C++ и должны анализировать ваш код QML изолированно. Поэтому у них не будет никакой информации о типах, зарегистрированных в C++. Чтобы (частично) решить эту проблему, были введены файлы "qmltypes". При разработке плагина QML рекомендуется поместить файл с именем "plugins.qmltypes" рядом с двоичным файлом плагина. Файл qmltypes содержит метаинформацию о типах, зарегистрированных плагином. Qt Creator и другие инструменты могут затем обратиться к этой информации, чтобы предоставить вам лучший анализ вашего кода. Это работает, но только для плагинов. Если вы регистрируете свои типы непосредственно из основной программы, вы все еще сталкиваетесь с той же проблемой. Кроме того, вы заканчиваете указанием ваших типов дважды, один раз в C++ и один раз в формате qmltypes. Чтобы (частично) решить проблему избыточной спецификации типа, доступен инструмент под названием "qmlplugindump". Этот инструмент загрузит ваш плагин так же, как и механизм QML. Затем он извлечет информацию обо всех типах, содержащихся в нем, для создания файла plugins.qmltypes. Это также позволит выполнить несвязанный код в вашем плагине, и он будет работать, только если вы компилируете свой плагин для той же платформы, на которой работает qmlplugindump. На практике это не работает для кросс-скомпилированных сборок.

Учитывая все эти камни преткновения, система регистрации типов была переработана в Qt 5.15. Вы не должны больше вызывать qmlRegisterType() и друзей процедурно. Вместо этого набор макросов, которые вы можете добавить в объявления классов, предоставляется в qqml.h. Эти макросы помечают тип как экспортированный в QML. Наиболее важным из них является "QML_ELEMENT". Он предоставляет класс обёртку в QML как элемент, названный именем класса C++. Компилятор мета-объектов (moc) найдет информацию, указанную таким образом. Когда передается параметр "--output-json", он предоставляет файл JSON, который содержит всю информацию метатипа в машинно-независимом и читаемом виде. Вы можете запустить это поведение, указав "CONFIG += metatypes" в вашем файле проекта qmake. Затем новый инструмент с именем "qmltyperegistrar" считывает этот файл метатипов и, возможно, связанные с ним файлы, и генерирует файл C++, содержащий функцию, которая регистрирует все типы, отмеченные соответствующими макросами, а также файл qmltypes только с информацией о типе, релевантной для модуля QML определенной вашим приложением. Для этого ему необходимо знать имя модуля и основную версию. Вы можете указать это в файле проекта qmake, используя переменные QML_IMPORT_NAME" и "QML_IMPORT_MAJOR_VERSION". Минорная версия не указывается. qmltyperegistrar найдет исправленные свойства и методы в данных метатипа и, соответственно, зарегистрирует разные версии типа. Это определяет минорные версии, под которыми доступен модуль. Вы также можете сделать тип доступным из определенной минорной версии, добавив макрос "QML_ADDED_IN_MINOR_VERSION(x)".

Как только система сборки настроена таким образом, вы можете инициировать фактическую регистрацию, добавив "CONFIG += qmltypes". Параметр "qmltypes" CONFIG подразумевает "metatypes". Вам не нужно указывать оба.

Такая статическая регистрация типов C++ для QML будет генерировать не только файлы qmltypes для плагинов, но и для вашего основного приложения. Последние файлы называются "app.qmltypes" и должны быть расположены рядом с двоичным файлом вашего приложения, точно так же, как "plugins.qmltypes" должен быть расположен рядом с плагином, на который он ссылается.

Чтобы проиллюстрировать это, давайте преобразуем приложение, которое динамически регистрирует типы, в приложение, которое статически регистрирует те же типы. Это уже было сделано со всеми примерами QML и QtQuick. Давайте посмотрим на основной пример "Adding Types" ("Добавление типов"). В Qt 5.14 и ранее у примера была следующая строка кода в файле main.cpp:

qmlRegisterType<Person>("People", 1,0, "Person");

Это позволит зарегистрировать C++ class "Person" в качестве элемента QML, также называемого "Person", в модуле "People" в версии 1.0. Эта строка исчезла в Qt 5.15. Вместо этого в файл adding.pro были добавлены следующие строки:

CONFIG += qmltypes
QML_IMPORT_NAME = People
QML_IMPORT_MAJOR_VERSION = 1

Эти строки указывают имя импорта и основную версию для всех типов, представленных в QML. Наконец, наиболее важным изменением является макрос "QML_ELEMENT", добавленный в файл person.h:

class Person : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QString name READ name WRITE setName)
    Q_PROPERTY(int shoeSize READ shoeSize WRITE setShoeSize)
    QML_ELEMENT
public:
    Person(QObject *parent = nullptr);
    [...]
};

Этот "QML_ELEMENT" указывает qmltyperegistrar, чтобы зарегистрировать тип. Это все. Теперь вы можете указать столько "QML_ELEMENT", сколько захотите, каждый раз не набирая имя импорта версии и ревизии.

We recommend hosting TIMEWEB
We recommend hosting TIMEWEB
Stable hosting, on which the social network EVILEG is located. For projects on Django we recommend VDS hosting.
Support the author Donate

У меня вот возник вопрос, как понимаю adding.pro дял добавления макросов это проектный файл?
А есть проект использует cmake, как там с этим обстоит?

Скорее всего также, как и для установки всех остальных переменых в CMake, через использование set

Comments

Only authorized users can post comments.
Please, Log in or Sign up
How to become an author?

Contribute to the evolution of the EVILEG community.

Learn how to become a site author.

Learn it
Donate

Good day, Dear Users!!!

I am Evgenii Legotckoi, developer of EVILEG. And it is my hobby project, which helps to learn programming another programmers and developers

If the site helped you, and you want also support the development of the site, than you can donate by following ways

PayPalYandex.Money
Timeweb

Let me recommend you the excellent hosting on which EVILEG is located.

For many years, Timeweb has been proving his stability.

For projects on Django I recommend VDS hosting

View Hosting
KA

C++ - Тест 003. Условия и циклы

  • Result:78points,
  • Rating points2
R

C++ - Test 002. Constants

  • Result:75points,
  • Rating points2
R

C++ - Test 001. The first program and data types

  • Result:73points,
  • Rating points1
Last comments
V

Django - Tutorial 027. Implementation Google reCAPTCHA

Спасибо. Только использую декоратор не в urls.py а перед views
R

Qt WinAPI - Lesson 001. How to collect all DLL, which used in Qt project?

Вы меня не совсем правильно поняли, но все равно спасибо, принял все к сведению. Все сделал как вы сказали, все отлично работает, еще раз огромнейшее спасибо) Разве что только что были опять про…

Qt WinAPI - Lesson 001. How to collect all DLL, which used in Qt project?

Стоило перед использованием что ли инструкцию прочитать https://www.cyberforum.ru/blogs/131347/blog2457.html "После сборки при запуске требовались dll," Ясное дело стоило задепло…
R
R

Qt WinAPI - Lesson 001. How to collect all DLL, which used in Qt project?

Да, собралось. После сборки при запуске требовались dll, перекинул всю папки bin, plugins(не знаю как можно было сделать более умно). Как я понял в первой строке путь к екзешнику вставляю, втор…
Now discuss on the forum

QML+QtGraphicalEffects

да, сборку делал без параметра поиска qml, хотя dll QtGraphicalEffects он подтягивает, когда я добавил всю папку QtGraphicalEffects в проект - то заработало, похоже что именно qml-файлов ему не …

Не работают слоты/сигналы

и посмотрите работу с потоками в Qt, там подробно описано как передавать данные с одного в потока в другой при помощи сигналов и слотов

Как в Qt в qmenu добавить scrollarea

Вот это наследованный класс меню. Но посути это обычное меню. #pragma once#include <QtWidgets>class TransMenu : public QMenu { Q_OBJECTpublic: TransMenu(QWidget* parent = …

Qt C++ и Python

Красиво/некрасиво - это скорее моё личное отношение. Если есть возможность ограничить количество интсрументов, то лучше ограничить. Но не зацикливайтесь на этом. Если у вас есть скрипты Py…

Qt + OpenGL glDeleteVertexArrays

Я не уверен, поскольку с OpenGL очень мало работал. Но может быть OpenGL контекст виджета нужно переинициализовывать. И ещё виджет стоит удалять через метод deleteLater() а не п…
About
Services
© EVILEG 2015-2020
Recommend hosting TIMEWEB