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 Qt5 example of Q_PROPERTY usage – header
Fig. 1 Qt5 example of Q_PROPERTY usage – header
Fig. 2 Qt5 example of Q_PROPERTY usage – cpp
Fig. 2 Qt5 example of Q_PROPERTY usage – cpp
Fig. 3 Qt6 example of Q_PROPERTY usage – header
Fig. 3 Qt6 example of Q_PROPERTY usage – header
Fig. 4 Qt6 example of Q_PROPERTY usage – cpp
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 Usage of context property and Q_PROPERTY
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 BINDABLE usage
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 Syntax difference between public slot and function with Q_INVOKABLE macro
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 Example of Connections usage
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 Two ways of getting the QObject* of QML object
Fig. 10 Two ways of getting the QObject* of QML object
Fig. 11 Two ways of changing property value from C++
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
5/5 ( votes: 4)
Rating:
5/5 ( votes: 4)
Author
Avatar
Tomasz Broniszewski

The Graduate of the Lublin University of Technology. Software engineer with 9 years of experience and almost 8 years with C++ & Qt/QML in commercial projects. If there is some spare time between sleep, work and parenting, he chooses powerlifting training.

Leave a comment

Your email address will not be published. Required fields are marked *

You might also like

More articles

Don't miss out

Subscribe to our blog and receive information about the latest posts.

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

Natalia Competency Center Director

Get an offer

Join Sii

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

Apply Apply

Paweł Process Owner

Join Sii

SUBMIT

Ta treść jest dostępna tylko w jednej wersji językowej.
Nastąpi przekierowanie do strony głównej.

Czy chcesz opuścić tę stronę?