{"id":417,"date":"2024-01-31T10:19:54","date_gmt":"2024-01-31T09:19:54","guid":{"rendered":"https:\/\/sii.ua\/blog\/?p=417"},"modified":"2024-02-16T09:43:55","modified_gmt":"2024-02-16T08:43:55","slug":"communication-methods-between-c-qt-and-qml","status":"publish","type":"post","link":"https:\/\/sii.ua\/blog\/en\/communication-methods-between-c-qt-and-qml\/","title":{"rendered":"Communication methods between C++\/Qt and QML"},"content":{"rendered":"\n<p>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.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Q_PROPERTY macro<\/strong><\/h2>\n\n\n\n<p>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 \u2013 MEMBER). The type could be defined by the user or one of the types supported by Qt could be used.<\/p>\n\n\n\n<p>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).<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Most common accessors<\/strong><\/h2>\n\n\n\n<p>The most common accessors are:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>READ \u2013 getter, must return either the property&#8217;s type or a const reference to that type.<\/li>\n\n\n\n<li>WRITE \u2013 setter, it must return void and must take exactly one argument, either of the property&#8217;s type or a pointer or reference to that type.<\/li>\n\n\n\n<li>MEMBER \u2013 could work instead of READ and WRITE, giving direct access to a variable. However, it\u2019s possible to use READ <strong>or<\/strong> WRITE in addition to MEMBER.<\/li>\n\n\n\n<li>RESET \u2013 reset the property to the default value, The RESET function must return void and take no parameters.<\/li>\n\n\n\n<li>NOTIFY \u2013 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.<\/li>\n\n\n\n<li>USER (bool) \u2013 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).<\/li>\n\n\n\n<li>CONSTANT \u2013 means that the property value is constant (exclude WRITE and NOTIFY).<\/li>\n\n\n\n<li>FINAL &#8211; property will not be overridden by a derived class.<\/li>\n\n\n\n<li>REQUIRED \u2013 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.<\/li>\n\n\n\n<li>BINDABLE (from Qt 6.0) \u2013 indicates that the property supports bindings.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Creating a class with Q_Property macro<\/strong><\/h2>\n\n\n\n<p>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 \u2026 does the same thing on QML side but has more to offer for C++.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.ua\/blog\/wp-content\/uploads\/2024\/01\/Fig.-1.png\"><img decoding=\"async\" width=\"773\" height=\"304\" src=\"https:\/\/sii.ua\/blog\/wp-content\/uploads\/2024\/01\/Fig.-1.png\" alt=\"Qt5 example of Q_PROPERTY usage \u2013 header\" class=\"wp-image-418\" srcset=\"https:\/\/sii.ua\/blog\/wp-content\/uploads\/2024\/01\/Fig.-1.png 773w, https:\/\/sii.ua\/blog\/wp-content\/uploads\/2024\/01\/Fig.-1-300x118.png 300w, https:\/\/sii.ua\/blog\/wp-content\/uploads\/2024\/01\/Fig.-1-768x302.png 768w\" sizes=\"(max-width: 773px) 100vw, 773px\" \/><\/a><figcaption class=\"wp-element-caption\"><em>Fig. 1 Qt5 example of Q_PROPERTY usage \u2013 header<\/em><\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.ua\/blog\/wp-content\/uploads\/2024\/01\/Fig.-2.png\"><img decoding=\"async\" width=\"571\" height=\"175\" src=\"https:\/\/sii.ua\/blog\/wp-content\/uploads\/2024\/01\/Fig.-2.png\" alt=\"Qt5 example of Q_PROPERTY usage \u2013 cpp\" class=\"wp-image-420\" srcset=\"https:\/\/sii.ua\/blog\/wp-content\/uploads\/2024\/01\/Fig.-2.png 571w, https:\/\/sii.ua\/blog\/wp-content\/uploads\/2024\/01\/Fig.-2-300x92.png 300w\" sizes=\"(max-width: 571px) 100vw, 571px\" \/><\/a><figcaption class=\"wp-element-caption\"><em>Fig. 2 Qt5 example of Q_PROPERTY usage \u2013 cpp<\/em><\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.ua\/blog\/wp-content\/uploads\/2024\/01\/Fig.-3.png\"><img decoding=\"async\" width=\"717\" height=\"240\" src=\"https:\/\/sii.ua\/blog\/wp-content\/uploads\/2024\/01\/Fig.-3.png\" alt=\"Qt6 example of Q_PROPERTY usage \u2013 header\" class=\"wp-image-422\" srcset=\"https:\/\/sii.ua\/blog\/wp-content\/uploads\/2024\/01\/Fig.-3.png 717w, https:\/\/sii.ua\/blog\/wp-content\/uploads\/2024\/01\/Fig.-3-300x100.png 300w\" sizes=\"(max-width: 717px) 100vw, 717px\" \/><\/a><figcaption class=\"wp-element-caption\"><em>Fig. 3 Qt6 example of Q_PROPERTY usage \u2013 header<\/em><\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.ua\/blog\/wp-content\/uploads\/2024\/01\/Fig.-4.png\"><img decoding=\"async\" width=\"536\" height=\"94\" src=\"https:\/\/sii.ua\/blog\/wp-content\/uploads\/2024\/01\/Fig.-4.png\" alt=\"Qt6 example of Q_PROPERTY usage \u2013 cpp\" class=\"wp-image-424\" srcset=\"https:\/\/sii.ua\/blog\/wp-content\/uploads\/2024\/01\/Fig.-4.png 536w, https:\/\/sii.ua\/blog\/wp-content\/uploads\/2024\/01\/Fig.-4-300x53.png 300w\" sizes=\"(max-width: 536px) 100vw, 536px\" \/><\/a><figcaption class=\"wp-element-caption\"><em>Fig. 4 Qt6 example of Q_PROPERTY usage \u2013 cpp<\/em><\/figcaption><\/figure>\n\n\n\n<p>And to the point, one way to access the <em>variable<\/em> property from QML is <strong>setContextProperty<\/strong> \u2013 exposing instance (one) to every component loaded by the engine. Object underneath <em>testObj<\/em> could be now used in QML by the name <em>myTest<\/em>. Usage is limited to Q_PROPERTY, signals and public slots (or Q_INVOKABLE functions). But it grants easy access.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.ua\/blog\/wp-content\/uploads\/2024\/01\/Fig.-6.png\"><img decoding=\"async\" width=\"331\" height=\"114\" src=\"https:\/\/sii.ua\/blog\/wp-content\/uploads\/2024\/01\/Fig.-6.png\" alt=\"Usage of context property and Q_PROPERTY\" class=\"wp-image-426\" srcset=\"https:\/\/sii.ua\/blog\/wp-content\/uploads\/2024\/01\/Fig.-6.png 331w, https:\/\/sii.ua\/blog\/wp-content\/uploads\/2024\/01\/Fig.-6-300x103.png 300w\" sizes=\"(max-width: 331px) 100vw, 331px\" \/><\/a><figcaption class=\"wp-element-caption\"><em>Fig. 6 Usage of context property and Q_PROPERTY<\/em><\/figcaption><\/figure>\n\n\n\n<p>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.<\/p>\n\n\n\n<p>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.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.ua\/blog\/wp-content\/uploads\/2024\/01\/Fig.-7.png\"><img decoding=\"async\" width=\"431\" height=\"144\" src=\"https:\/\/sii.ua\/blog\/wp-content\/uploads\/2024\/01\/Fig.-7.png\" alt=\"BINDABLE usage\" class=\"wp-image-428\" srcset=\"https:\/\/sii.ua\/blog\/wp-content\/uploads\/2024\/01\/Fig.-7.png 431w, https:\/\/sii.ua\/blog\/wp-content\/uploads\/2024\/01\/Fig.-7-300x100.png 300w\" sizes=\"(max-width: 431px) 100vw, 431px\" \/><\/a><figcaption class=\"wp-element-caption\"><em>Fig. 7 BINDABLE usage<\/em><\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Q_INVOKABLE &amp; Public slots<\/strong><\/h2>\n\n\n\n<p>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 <em>QQmlEngine::setObjectOwnership<\/em> can be used.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.ua\/blog\/wp-content\/uploads\/2024\/01\/Fig.-8.png\"><img decoding=\"async\" width=\"220\" height=\"78\" src=\"https:\/\/sii.ua\/blog\/wp-content\/uploads\/2024\/01\/Fig.-8.png\" alt=\"Syntax difference between public slot and function with Q_INVOKABLE macro\" class=\"wp-image-430\"\/><\/a><figcaption class=\"wp-element-caption\"><em>Fig. 8 Syntax difference between public slot and function with Q_INVOKABLE macro<\/em><\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>QML Connections<\/strong><\/h2>\n\n\n\n<p>QML component that can be used when:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Multiple connections to the same signal are required.<\/li>\n\n\n\n<li>Creating connections outside the scope of the signal sender.<\/li>\n\n\n\n<li>Connecting to targets not defined in QML.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.ua\/blog\/wp-content\/uploads\/2024\/01\/Fig.-9.png\"><img decoding=\"async\" width=\"378\" height=\"108\" src=\"https:\/\/sii.ua\/blog\/wp-content\/uploads\/2024\/01\/Fig.-9.png\" alt=\"Example of Connections usage\" class=\"wp-image-432\" srcset=\"https:\/\/sii.ua\/blog\/wp-content\/uploads\/2024\/01\/Fig.-9.png 378w, https:\/\/sii.ua\/blog\/wp-content\/uploads\/2024\/01\/Fig.-9-300x86.png 300w\" sizes=\"(max-width: 378px) 100vw, 378px\" \/><\/a><figcaption class=\"wp-element-caption\"><em>Fig. 9 Example of Connections usage<\/em><\/figcaption><\/figure>\n\n\n\n<p>This could be used to intercept any signal that is accessible from defined target. Syntax shown above was introduced in Qt 5.15.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Accessing QML object from C++<\/h2>\n\n\n\n<p>It may be needed to change QML property from C++ e.g for testing purposes. To do this there are: <em>QObject::setProperty()<\/em> or <em>QQmlProperty::write()<\/em>. Firstly, it will be required to extract a particular QObject pointer like below:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.ua\/blog\/wp-content\/uploads\/2024\/01\/Fig.-10.png\"><img decoding=\"async\" width=\"512\" height=\"120\" src=\"https:\/\/sii.ua\/blog\/wp-content\/uploads\/2024\/01\/Fig.-10.png\" alt=\"Two ways of getting the QObject* of QML object\" class=\"wp-image-434\" srcset=\"https:\/\/sii.ua\/blog\/wp-content\/uploads\/2024\/01\/Fig.-10.png 512w, https:\/\/sii.ua\/blog\/wp-content\/uploads\/2024\/01\/Fig.-10-300x70.png 300w\" sizes=\"(max-width: 512px) 100vw, 512px\" \/><\/a><figcaption class=\"wp-element-caption\"><em>Fig. 10 Two ways of getting the QObject* of <\/em>QML <em>object<\/em><\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full is-resized\"><a href=\"https:\/\/sii.ua\/blog\/wp-content\/uploads\/2024\/01\/Fig.-11.png\"><img decoding=\"async\" width=\"299\" height=\"36\" src=\"https:\/\/sii.ua\/blog\/wp-content\/uploads\/2024\/01\/Fig.-11.png\" alt=\"Two ways of changing property value from C++\" class=\"wp-image-436\" style=\"width:291px;height:auto\"\/><\/a><figcaption class=\"wp-element-caption\"><em>Fig. 11 Two ways of changing property value from C++<\/em><\/figcaption><\/figure>\n\n\n\n<p>If changing property is not enough it is even possible to call method (using <em>QMetaObject::invokeMethod()<\/em>) as all QML methods are exposed to the meta-object system.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Summary<\/strong><\/h2>\n\n\n\n<p>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.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Sources<\/h2>\n\n\n\n<ol class=\"wp-block-list\" style=\"list-style-type:1\">\n<li><a href=\"https:\/\/doc.qt.io\/qt-6\/qtqml-cppintegration-exposecppattributes.html\" rel=\"nofollow\" >Qt Documentations \u2013\u00ad Exposing Attributes of C++ Types to QML<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/doc.qt.io\/qt-6\/qqmlcontext.html\" rel=\"nofollow\" >Qt Documentations \u2013 QQmlContext Class<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/doc.qt.io\/qt-6\/qml-qtqml-connections.html\" rel=\"nofollow\" >Qt Documentation \u2013 Connections QML Type<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/doc.qt.io\/qt-6\/qqmlcontext.html#setContextProperty\" rel=\"nofollow\" >Qt Documentation \u2013 QQmlContext Class, Set ContextProperty<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/doc.qt.io\/qt-6\/properties.html\" rel=\"nofollow\" >Qt Documentation \u2013 The Property System<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/doc.qt.io\/qt-6\/bindableproperties.html\" rel=\"nofollow\" >Qt Documentation \u2013 Qt Bindable Properties<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/doc.qt.io\/qt-6\/qtqml-cppintegration-interactqmlfromcpp.html\" rel=\"nofollow\" >Qt Documentation \u2013 Interacting with QML Objects from C++<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/doc-snapshots.qt.io\/qt6-dev\/qobjectbindableproperty.html\" rel=\"nofollow\" >Qt Doc Snapshots \u2013 QObjectBindableProperty Class<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/www.ics.com\/blog\/qt6-bindings-deliver-increased-performance\" rel=\"nofollow\" >ICS \u2013 Qt 6 Bindings<\/a><\/li>\n<\/ol>\n\n\n<div class=\"kk-star-ratings kksr-auto kksr-align-left kksr-valign-bottom\"\n    data-payload='{&quot;align&quot;:&quot;left&quot;,&quot;id&quot;:&quot;417&quot;,&quot;slug&quot;:&quot;default&quot;,&quot;valign&quot;:&quot;bottom&quot;,&quot;ignore&quot;:&quot;&quot;,&quot;reference&quot;:&quot;auto&quot;,&quot;class&quot;:&quot;&quot;,&quot;count&quot;:&quot;0&quot;,&quot;legendonly&quot;:&quot;&quot;,&quot;readonly&quot;:&quot;&quot;,&quot;score&quot;:&quot;0&quot;,&quot;starsonly&quot;:&quot;&quot;,&quot;best&quot;:&quot;5&quot;,&quot;gap&quot;:&quot;2&quot;,&quot;greet&quot;:&quot;&quot;,&quot;legend&quot;:&quot;0\\\/5&quot;,&quot;size&quot;:&quot;30&quot;,&quot;title&quot;:&quot;Communication methods between C++\\\/Qt and QML&quot;,&quot;width&quot;:&quot;0&quot;,&quot;_legend&quot;:&quot;{score}\\\/5&quot;,&quot;font_factor&quot;:&quot;1.25&quot;}'>\n            \n<div class=\"kksr-stars\">\n    \n<div class=\"kksr-stars-inactive\">\n            <div class=\"kksr-star\" data-star=\"1\" style=\"padding-right: 2px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 30px; height: 30px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"2\" style=\"padding-right: 2px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 30px; height: 30px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"3\" style=\"padding-right: 2px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 30px; height: 30px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"4\" style=\"padding-right: 2px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 30px; height: 30px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"5\" style=\"padding-right: 2px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 30px; height: 30px;\"><\/div>\n        <\/div>\n    <\/div>\n    \n<div class=\"kksr-stars-active\" style=\"width: 0px;\">\n            <div class=\"kksr-star\" style=\"padding-right: 2px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 30px; height: 30px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 2px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 30px; height: 30px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 2px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 30px; height: 30px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 2px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 30px; height: 30px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 2px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 30px; height: 30px;\"><\/div>\n        <\/div>\n    <\/div>\n<\/div>\n                \n\n<div class=\"kksr-legend\" style=\"font-size: 24px;\">\n            <span class=\"kksr-muted\"><\/span>\n    <\/div>\n    <\/div>\n","protected":false},"excerpt":{"rendered":"<p>When the decision is done and the technology stack lists C++, Qt and QML it is time to do some &hellip; <a class=\"continued-btn\" href=\"https:\/\/sii.ua\/blog\/en\/communication-methods-between-c-qt-and-qml\/\">Continued<\/a><\/p>\n","protected":false},"author":21,"featured_media":438,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_editorskit_title_hidden":false,"_editorskit_reading_time":0,"_editorskit_is_block_options_detached":false,"_editorskit_block_options_position":"{}","inline_featured_image":false,"footnotes":""},"categories":[1],"tags":[89,90,91],"class_list":["post-417","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-hard-development","tag-c","tag-embedded","tag-qml"],"acf":[],"aioseo_notices":[],"featured_media_url":"https:\/\/sii.ua\/blog\/wp-content\/uploads\/2024\/01\/Communication-methods-between-C.jpg","category_names":["Hard development"],"_links":{"self":[{"href":"https:\/\/sii.ua\/blog\/en\/wp-json\/wp\/v2\/posts\/417"}],"collection":[{"href":"https:\/\/sii.ua\/blog\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sii.ua\/blog\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sii.ua\/blog\/en\/wp-json\/wp\/v2\/users\/21"}],"replies":[{"embeddable":true,"href":"https:\/\/sii.ua\/blog\/en\/wp-json\/wp\/v2\/comments?post=417"}],"version-history":[{"count":5,"href":"https:\/\/sii.ua\/blog\/en\/wp-json\/wp\/v2\/posts\/417\/revisions"}],"predecessor-version":[{"id":444,"href":"https:\/\/sii.ua\/blog\/en\/wp-json\/wp\/v2\/posts\/417\/revisions\/444"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/sii.ua\/blog\/en\/wp-json\/wp\/v2\/media\/438"}],"wp:attachment":[{"href":"https:\/\/sii.ua\/blog\/en\/wp-json\/wp\/v2\/media?parent=417"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sii.ua\/blog\/en\/wp-json\/wp\/v2\/categories?post=417"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sii.ua\/blog\/en\/wp-json\/wp\/v2\/tags?post=417"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}