mafulechka
mafulechkaMarch 26, 2020, 3:18 p.m.

QML Type Registration in Qt 5.15

Qt 5.15 provides a much improved way to represent C++ types for QML. Now you can specify the name and version of your module in a central place, and you no longer need to specify minor versions or revisions. In addition, the specifics of QML type registration can now be declared in a C++ class declaration.


So far, a common way to make C++ types available in QML has been to use the registration functions provided in the qqml.h header: qmlRegisterType(), qmlRegisterSingletonType(), qmlRegisterUncreatableType(), etc. This approach has its drawbacks:

you should always keep your type registrations in sync with the actual types. This is especially tedious if you're using revisions to make properties available across different import versions. Even if it isn't, the fact that you have to specify registration separately from the type is cumbersome, as you can easily lose track of how you registered which types into which modules.

Also, since you are registering your types procedurally, any QML tool cannot automatically determine which types are available in which imports. Qt Creator does have some heuristics that try to detect common logging patterns in C++ code, but this is incomplete. Finding out whether a program will perform a particular registration is equivalent to solving the stopping problem. Simpler tools like qmllint or qmlformat have no knowledge of C++ code and must parse your QML code in isolation. Therefore, they will not have any information about types registered in C++. To (partially) solve this problem, "qmltypes" files were introduced. When developing a QML plugin, it is recommended to place a file named "plugins.qmltypes" next to the plugin binary. The qmltypes file contains meta information about the types registered by the plugin. Qt Creator and other tools can then refer to this information to provide you with a better analysis of your code. It works, but only for plugins. If you are registering your types directly from the main program, you still run into the same problem. Also, you end up specifying your types twice, once in C++ and once in the qmltypes format. To (partially) solve the problem of redundant type specification, a tool called "qmlplugindump" is available. This tool will load your plugin just like the QML engine. It will then extract information about all the types it contains to create a plugins.qmltypes file. This will also allow unrelated code in your plugin to execute, and it will only work if you are compiling your plugin for the same platform that qmlplugindump is running on. In practice, this does not work for cross-compiled builds.

Given all these stumbling blocks, the type registration system has been redesigned in Qt 5.15. You should no longer call qmlRegisterType() and friends procedurally. Instead, a set of macros that you can add to class declarations is provided in qqml.h. These macros mark the type as exported to QML. The most important of these is "QML_ELEMENT". It provides a wrapper class in QML as an element named after the C++ class. The Meta Object Compiler (moc) will find the information specified in this way. When the "--output-json" option is passed, it provides a JSON file that contains all of the metatype information in a machine-independent and readable way. You can trigger this behavior by specifying "CONFIG += metatypes" in your qmake project file. A new tool named "qmltyperegistrar" then reads this metatype file and possibly related files and generates a C++ file containing a function that registers all types marked with the appropriate macros, as well as a qmltypes file with only type information relevant to QML module defined by your application. To do this, it needs to know the module name and major version. You can specify this in the qmake project file using the QML_IMPORT_NAME" and "QML_IMPORT_MAJOR_VERSION" variables. No minor version is specified. qmltyperegistrar will find fixed properties and methods in the metatype data and register different versions of the type accordingly. This determines the minor versions under which the module is available You can also make a type available from a specific minor version by adding the macro "QML_ADDED_IN_MINOR_VERSION(x)".

Once the build system is set up this way, you can initiate the actual registration by adding "CONFIG += qmltypes". The "qmltypes" CONFIG parameter implies "metatypes". You don't need to specify both.

This kind of static C++ type registration for QML will generate not only qmltypes files for plugins, but also for your main application. The latter files are called "app.qmltypes" and should be placed next to your application binary, just like "plugins.qmltypes" should be placed next to the plugin it refers to.

To illustrate this, let's convert an application that dynamically registers types to an application that statically registers the same types. This has already been done with all the QML and QtQuick examples. Let's look at a basic "Adding Types" example. In Qt 5.14 and earlier, the example had the following line of code in the main.cpp file:

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

This will allow the C++ class "Person" to be registered as a QML element, also called "Person", in the "People" module in version 1.0. This line is gone in Qt 5.15. Instead, the following lines were added to the adding.pro file:

CONFIG += qmltypes
QML_IMPORT_NAME = People
QML_IMPORT_MAJOR_VERSION = 1

These lines specify the import name and major version for all types represented in QML. Finally, the most important change is the "QML_ELEMENT" macro added to the person.h file:

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);
    [...]
};

This "QML_ELEMENT" tells qmltyperegistrar to register the type. It's all. Now you can specify as many "QML_ELEMENT" as you want without typing version and revision import name each time.

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.

Do you like it? Share on social networks!

BlinCT
  • March 26, 2020, 8:50 p.m.

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

Evgenii Legotckoi
  • March 27, 2020, 2:36 p.m.

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

Comments

Only authorized users can post comments.
Please, Log in or Sign up
Lz

C ++ - Test 004. Pointers, Arrays and Loops

  • Result:70points,
  • Rating points1
РК

Qt - Test 001. Signals and slots

  • Result:84points,
  • Rating points4
Last comments
k
kmssrFeb. 9, 2024, 7:43 a.m.
Qt Linux - Lesson 001. Autorun Qt application under Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
Qt WinAPI - Lesson 007. Working with ICMP Ping in Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
EVA
EVADec. 25, 2023, 11:30 p.m.
Boost - static linking in CMake project under Windows Ошибка LNK1104 часто возникает, когда компоновщик не может найти или открыть файл библиотеки. В вашем случае, это файл libboost_locale-vc142-mt-gd-x64-1_74.lib из библиотеки Boost для C+…
J
JonnyJoDec. 25, 2023, 9:38 p.m.
Boost - static linking in CMake project under Windows Сделал всё по-как у вас, но выдаёт ошибку [build] LINK : fatal error LNK1104: не удается открыть файл "libboost_locale-vc142-mt-gd-x64-1_74.lib" Хоть убей, не могу понять в чём дел…
G
GvozdikDec. 19, 2023, 10:01 a.m.
Qt/C++ - Lesson 056. Connecting the Boost library in Qt for MinGW and MSVC compilers Для решения твой проблемы добавь в файл .pro строчку "LIBS += -lws2_32" она решит проблему , лично мне помогло.
Now discuss on the forum
BlinCT
BlinCTJune 25, 2024, 1 p.m.
Нарисовать кривую в qml Всем привет. Имеется Лист листов с тосками, точки получаны интерполяцией Лагранжа. Вопрос, как этими точками нарисовать кривую? ChartView отпадает сразу, в qt6.7 появился новый элемент…
Evgenii Legotckoi
Evgenii LegotckoiJune 25, 2024, 3:11 a.m.
добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
BlinCT
BlinCTMay 5, 2024, 5:46 p.m.
Написать свой GraphsView Всем привет. В Qt есть давольно старый обьект дял работы с графиками ChartsView и есть в 6.7 новый но очень сырой и со слабым функционалом GraphsView. По этой причине я хочу написать х…
Evgenii Legotckoi
Evgenii LegotckoiMay 3, 2024, 2:07 a.m.
Мобильное приложение на C++Qt и бэкенд к нему на Django Rest Framework Добрый день. По моему мнению - да, но то, что будет касаться вызовов к функционалу Андроида, может создать огромные трудности.
IscanderChe
IscanderCheApril 30, 2024, 4:22 p.m.
Во Flask рендер шаблона не передаётся в браузер Доброе утро! Имеется вот такой шаблон: <!doctype html><html> <head> <title>{{ title }}</title> <link rel="stylesheet" href="{{ url_…

Follow us in social networks