Send your request Join Sii

When the decision is done and the technology stack lists C++, Qt and QML it is time to do some work. To make it efficient and clean it is good to know all the available options. So, one of the topics that will come out at the beginning is the communication method between the frontend and the backend.

Q_PROPERTY macro

One of the most popular is the usage of Q_PROPERTY macro. Every class that derives from QObject (and contains Q_OBJECT macro) can use it. The other option is to use Q_GADGET macro. The simplest syntax requires type of the variable, its name and the getter (marked as READ or direct access – MEMBER). The type could be defined by the user or one of the types supported by Qt could be used.

There are a lot of features that Q_PROPERTY offers but aside of the required ones, often used are WRITE and NOTIFY. The first works as a setter (it requires a param of the same type as the property itself) and the second one is a signal that notifies any changes of the property (at least it should, after receiving the signal, the getter is called to check the value).

Most common accessors

The most common accessors are:

  • READ – getter, must return either the property’s type or a const reference to that type.
  • WRITE – setter, it must return void and must take exactly one argument, either of the property’s type or a pointer or reference to that type.
  • MEMBER – could work instead of READ and WRITE, giving direct access to a variable. However, it’s possible to use READ or WRITE in addition to MEMBER.
  • RESET – reset the property to the default value, The RESET function must return void and take no parameters.
  • NOTIFY – should specify the signal which is emitted when the value (of the property) changes. Qt emits automatically that signal when needed for MEMBER properties that do not have an explicit setter.
  • USER (bool) – attribute indicates whether the property is designated as the user-facing or user-editable property for the class. Normally, there is only one USER property per class (default false).
  • CONSTANT – means that the property value is constant (exclude WRITE and NOTIFY).
  • FINAL – property will not be overridden by a derived class.
  • REQUIRED – the property should be set by a user of the class. In QML, classes with REQUIRED properties cannot be instantiated unless all REQUIRED properties have been set.
  • BINDABLE (from Qt 6.0) – indicates that the property supports bindings.

Creating a class with Q_Property macro

Below there are two basic examples tow to create a class with Q_PROPERTY macro. The first is based on Qt5 and uses READ WRITE and NOTIFY, the second uses brand new BINDABLE and … does the same thing on QML side but has more to offer for C++.

Fig. 1 - Communication methods between C++/Qt and QML
Fig. 1 Qt5 example of Q_PROPERTY usage – header
Fig. 2 - Communication methods between C++/Qt and QML
Fig. 2 Qt5 example of Q_PROPERTY usage – cpp
Fig. 3 - Communication methods between C++/Qt and QML
Fig. 3 Qt6 example of Q_PROPERTY usage – header
Fig. 4 - Communication methods between C++/Qt and QML
Fig. 4 Qt6 example of Q_PROPERTY usage – cpp

And to the point, one way to access the variable property from QML is setContextProperty – exposing instance (one) to every component loaded by the engine. Object underneath testObj could be now used in QML by the name myTest. Usage is limited to Q_PROPERTY, signals and public slots (or Q_INVOKABLE functions). But it grants easy access.

Fig. 6 - Communication methods between C++/Qt and QML
Fig. 6 Usage of context property and Q_PROPERTY

Clicking on a button will result in incrementing the variable (calling setter) and through notification signal, the getter is called (READ) and all bindings on QML side are updated.

Maybe a few more words on BINDABLE as it enhances performance and introduces property binding also on C++ side. This help to simplify the program, by eliminating a lot of boilerplate code for tracking and reacting to dependency updates of different objects. Instead of using a setter, it is possible to simply assign a new value as shown below.

Fig. 7 - Communication methods between C++/Qt and QML
Fig. 7 BINDABLE usage

Q_INVOKABLE & Public slots

One of these allows calling the function directly from QML. One important disclaimer here. This will transfer ownership to QML side so e.g. if a pointer to an object is returned from the function beware of the garbage collector when C++ also uses this object. This could be tricky to investigate since a garbage collector could not be called right away. To manually change the object ownership QQmlEngine::setObjectOwnership can be used.

Fig. 8 - Communication methods between C++/Qt and QML
Fig. 8 Syntax difference between public slot and function with Q_INVOKABLE macro

QML Connections

QML component that can be used when:

  • Multiple connections to the same signal are required.
  • Creating connections outside the scope of the signal sender.
  • Connecting to targets not defined in QML.
Fig. 9 - Communication methods between C++/Qt and QML
Fig. 9 Example of Connections usage

This could be used to intercept any signal that is accessible from defined target. Syntax shown above was introduced in Qt 5.15.

Accessing QML object from C++

It may be needed to change QML property from C++ e.g for testing purposes. To do this there are: QObject::setProperty() or QQmlProperty::write(). Firstly, it will be required to extract a particular QObject pointer like below:

Fig. 10 - Communication methods between C++/Qt and QML
Fig. 10 Two ways of getting the QObject* of QML object
Fig. 11 - Communication methods between C++/Qt and QML
Fig. 11 Two ways of changing property value from C++

If changing property is not enough it is even possible to call method (using QMetaObject::invokeMethod()) as all QML methods are exposed to the meta-object system.

Summary

The article presented the ways of communication between the frontend and the backend, depending on particular needs. The different methods, starting from variable access, through function calls, acting on emitted signal and ending on QML object access from C++, are shown in the paper.

Sources

  1. Qt Documentations –­ Exposing Attributes of C++ Types to QML
  2. Qt Documentations – QQmlContext Class
  3. Qt Documentation – Connections QML Type
  4. Qt Documentation – QQmlContext Class, Set ContextProperty
  5. Qt Documentation – The Property System
  6. Qt Documentation – Qt Bindable Properties
  7. Qt Documentation – Interacting with QML Objects from C++
  8. Qt Doc Snapshots – QObjectBindableProperty Class
  9. ICS – Qt 6 Bindings
Rating:
Author

You might also like

More articles

Get an offer

If you have any questions or would like to learn more about our offer, feel free to contact us.

Send your request Send your request

Tomasz Ukraine Business Lead

Get an offer

Join Sii

Find the job that's right for you. Check out open positions and apply.

Apply Join Sii

Viktoriya Recruitment Specialist

Join Sii

SUBMIT

Цей контент доступний тільки в одній мовній версії.
Ви будете перенаправлені на головну сторінку.

Ви справді бажаєте залишити цю сторінку?