Sophie

Sophie

distrib > Mageia > 7 > i586 > media > core-updates > by-pkgid > 6e2327ca1c896c6d674ae53117299f21 > files > 198

qtdeclarative5-doc-5.12.6-1.mga7.noarch.rpm

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<!-- interactqmlfromcpp.qdoc -->
  <title>Interacting with QML Objects from C++ | Qt QML 5.12.6</title>
  <link rel="stylesheet" type="text/css" href="style/offline-simple.css" />
  <script type="text/javascript">
    document.getElementsByTagName("link").item(0).setAttribute("href", "style/offline.css");
    // loading style sheet breaks anchors that were jumped to before
    // so force jumping to anchor again
    setTimeout(function() {
        var anchor = location.hash;
        // need to jump to different anchor first (e.g. none)
        location.hash = "#";
        setTimeout(function() {
            location.hash = anchor;
        }, 0);
    }, 0);
  </script>
</head>
<body>
<div class="header" id="qtdocheader">
  <div class="main">
    <div class="main-rounded">
      <div class="navigationbar">
        <table><tr>
<td >Qt 5.12</td><td ><a href="qtqml-index.html">Qt QML</a></td><td >Interacting with QML Objects from C++</td></tr></table><table class="buildversion"><tr>
<td id="buildversion" width="100%" align="right"><a href="qtqml-index.html">Qt 5.12.6 Reference Documentation</a></td>
        </tr></table>
      </div>
    </div>
<div class="content">
<div class="line">
<div class="content mainContent">
<div class="sidebar">
<div class="toc">
<h3><a name="toc">Contents</a></h3>
<ul>
<li class="level1"><a href="#loading-qml-objects-from-c">Loading QML Objects from C++</a></li>
<li class="level1"><a href="#accessing-loaded-qml-objects-by-object-name">Accessing Loaded QML Objects by Object Name</a></li>
<li class="level1"><a href="#accessing-members-of-a-qml-object-type-from-c">Accessing Members of a QML Object Type from C++</a></li>
<li class="level2"><a href="#properties">Properties</a></li>
<li class="level2"><a href="#invoking-qml-methods">Invoking QML Methods</a></li>
<li class="level2"><a href="#connecting-to-qml-signals">Connecting to QML Signals</a></li>
</ul>
</div>
<div class="sidebar-content" id="sidebar-content"></div></div>
<h1 class="title">Interacting with QML Objects from C++</h1>
<span class="subtitle"></span>
<!-- $$$qtqml-cppintegration-interactqmlfromcpp.html-description -->
<div class="descr"> <a name="details"></a>
<p>All QML object types are QObject-derived types, whether they are internally implemented by the engine or <a href="qtqml-cppintegration-definetypes.html">defined by third-party sources</a>. This means the QML engine can use the Qt Meta Object System to dynamically instantiate any QML object type and inspect the created objects.</p>
<p>This is useful for creating QML objects from C++ code, whether to display a QML object that can be visually rendered, or to integrate non-visual QML object data into a C++ application. Once a QML object is created, it can be inspected from C++ in order to read and write to properties, invoke methods and receive signal notifications.</p>
<a name="loading-qml-objects-from-c"></a>
<h2 id="loading-qml-objects-from-c">Loading QML Objects from C++</h2>
<p>A QML document can be loaded with <a href="qqmlcomponent.html">QQmlComponent</a> or QQuickView. <a href="qqmlcomponent.html">QQmlComponent</a> loads a QML document as a C++ object that can then be modified from C++ code. QQuickView also does this, but as QQuickView is a QWindow-derived class, the loaded object will also be rendered into a visual display; QQuickView is generally used to integrate a displayable QML object into an application's user interface.</p>
<p>For example, suppose there is a <code>MyItem.qml</code> file that looks like this:</p>
<pre class="qml">

  import QtQuick 2.0

  Item {
      width: 100; height: 100
  }

</pre>
<p>This QML document can be loaded with <a href="qqmlcomponent.html">QQmlComponent</a> or QQuickView with the following C++ code. Using a <a href="qqmlcomponent.html">QQmlComponent</a> requires calling <a href="qqmlcomponent.html#create">QQmlComponent::create</a>() to create a new instance of the component, while a QQuickView automatically creates an instance of the component, which is accessible via QQuickView::rootObject():</p>
<div class="table"><table class="generic">
 <tr valign="top" class="odd"><td ><pre class="cpp">

  <span class="comment">// Using QQmlComponent</span>
  <span class="type"><a href="qqmlengine.html">QQmlEngine</a></span> engine;
  <span class="type"><a href="qqmlcomponent.html">QQmlComponent</a></span> component(<span class="operator">&amp;</span>engine<span class="operator">,</span>
          <span class="type">QUrl</span><span class="operator">::</span>fromLocalFile(<span class="string">&quot;MyItem.qml&quot;</span>));
  <span class="type">QObject</span> <span class="operator">*</span>object <span class="operator">=</span> component<span class="operator">.</span>create();
  ...
  <span class="keyword">delete</span> object;

</pre>
</td><td ><pre class="cpp">

  <span class="comment">// Using QQuickView</span>
  <span class="type">QQuickView</span> view;
  view<span class="operator">.</span>setSource(<span class="type">QUrl</span><span class="operator">::</span>fromLocalFile(<span class="string">&quot;MyItem.qml&quot;</span>));
  view<span class="operator">.</span>show();
  <span class="type">QObject</span> <span class="operator">*</span>object <span class="operator">=</span> view<span class="operator">.</span>rootObject();

</pre>
</td></tr>
</table></div>
<p>This <code>object</code> is the instance of the <code>MyItem.qml</code> component that has been created. You can now modify the item's properties using QObject::setProperty() or <a href="qqmlproperty.html#write">QQmlProperty::write</a>():</p>
<pre class="cpp">

  object<span class="operator">-</span><span class="operator">&gt;</span>setProperty(<span class="string">&quot;width&quot;</span><span class="operator">,</span> <span class="number">500</span>);
  <span class="type"><a href="qqmlproperty.html">QQmlProperty</a></span>(object<span class="operator">,</span> <span class="string">&quot;width&quot;</span>)<span class="operator">.</span>write(<span class="number">500</span>);

</pre>
<p>The difference between <code>QObject::setProperty()</code> and <code>QQmlProperty::write()</code> is that the latter will also remove the binding in addition to setting the property value. For example, suppose the <code>width</code> assignment above had been a binding to <code>height</code>:</p>
<pre class="cpp">

  width: height

</pre>
<p>If the <code>height</code> of the <code>Item</code> changed after the <code>object-&gt;setProperty(&quot;width&quot;, 500)</code> call, the <code>width</code> would be updated again, as the binding remains active. However, if the <code>height</code> changes after the <code>QQmlProperty(object, &quot;width&quot;).write(500)</code> call, the <code>width</code> will not be changed, as the binding does not exist anymore.</p>
<p>Alternatively, you can cast the object to its actual type and call methods with compile-time safety. In this case the base object of <code>MyItem.qml</code> is an Item, which is defined by the QQuickItem class:</p>
<pre class="cpp">

  <span class="type">QQuickItem</span> <span class="operator">*</span>item <span class="operator">=</span> qobject_cast<span class="operator">&lt;</span><span class="type">QQuickItem</span><span class="operator">*</span><span class="operator">&gt;</span>(object);
  item<span class="operator">-</span><span class="operator">&gt;</span>setWidth(<span class="number">500</span>);

</pre>
<p>You can also connect to any signals or call methods defined in the component using QMetaObject::invokeMethod() and QObject::connect(). See <a href="qtqml-cppintegration-interactqmlfromcpp.html#invoking-qml-methods">Invoking QML Methods</a> and <a href="qtqml-cppintegration-interactqmlfromcpp.html#connecting-to-qml-signals">Connecting to QML Signals</a> below for further details.</p>
<a name="accessing-loaded-qml-objects-by-object-name"></a>
<h2 id="accessing-loaded-qml-objects-by-object-name">Accessing Loaded QML Objects by Object Name</h2>
<p>QML components are essentially object trees with children that have siblings and their own children. Child objects of QML components can be located using the QObject::objectName property with QObject::findChild(). For example, if the root item in <code>MyItem.qml</code> had a child Rectangle item:</p>
<pre class="qml">

  import QtQuick 2.0

  Item {
      width: 100; height: 100

      Rectangle {
          anchors.fill: parent
          objectName: "rect"
      }
  }

</pre>
<p>The child could be located like this:</p>
<pre class="cpp">

  <span class="type">QObject</span> <span class="operator">*</span>rect <span class="operator">=</span> object<span class="operator">-</span><span class="operator">&gt;</span>findChild<span class="operator">&lt;</span><span class="type">QObject</span><span class="operator">*</span><span class="operator">&gt;</span>(<span class="string">&quot;rect&quot;</span>);
  <span class="keyword">if</span> (rect)
      rect<span class="operator">-</span><span class="operator">&gt;</span>setProperty(<span class="string">&quot;color&quot;</span><span class="operator">,</span> <span class="string">&quot;red&quot;</span>);

</pre>
<p>Note that an object may have multiple children with the same <code>objectName</code>. For example, ListView creates multiple instances of its delegate, so if its delegate is declared with a particular objectName, the ListView will have multiple children with the same <code>objectName</code>. In this case, QObject::findChildren() can be used to find all children with a matching <code>objectName</code>.</p>
<p><b>Warning:</b> Although it is possible to access QML objects from C++ and manipulate them, it is not the recommended approach, except for testing and prototyping purposes. One of the strengths of QML and C++ integration is the ability to implement UIs in QML separate from the C++ logic and dataset backend, and this fails if the C++ side starts manipulating QML directly. Such an approach also makes changing the QML UI difficult without affecting its C++ counterpart.</p>
<a name="accessing-members-of-a-qml-object-type-from-c"></a>
<h2 id="accessing-members-of-a-qml-object-type-from-c">Accessing Members of a QML Object Type from C++</h2>
<a name="properties"></a>
<h3 id="properties">Properties</h3>
<p>Any properties declared in a QML object are automatically accessible from C++. Given a QML item like this:</p>
<pre class="qml">

  // MyItem.qml
  import QtQuick 2.0

  Item {
      property int someNumber: 100
  }

</pre>
<p>The value of the <code>someNumber</code> property can be set and read using <a href="qqmlproperty.html">QQmlProperty</a>, or QObject::setProperty() and QObject::property():</p>
<pre class="cpp">

  <span class="type"><a href="qqmlengine.html">QQmlEngine</a></span> engine;
  <span class="type"><a href="qqmlcomponent.html">QQmlComponent</a></span> component(<span class="operator">&amp;</span>engine<span class="operator">,</span> <span class="string">&quot;MyItem.qml&quot;</span>);
  <span class="type">QObject</span> <span class="operator">*</span>object <span class="operator">=</span> component<span class="operator">.</span>create();

  qDebug() <span class="operator">&lt;</span><span class="operator">&lt;</span> <span class="string">&quot;Property value:&quot;</span> <span class="operator">&lt;</span><span class="operator">&lt;</span> <span class="type"><a href="qqmlproperty.html">QQmlProperty</a></span><span class="operator">::</span>read(object<span class="operator">,</span> <span class="string">&quot;someNumber&quot;</span>)<span class="operator">.</span>toInt();
  <span class="type"><a href="qqmlproperty.html">QQmlProperty</a></span><span class="operator">::</span>write(object<span class="operator">,</span> <span class="string">&quot;someNumber&quot;</span><span class="operator">,</span> <span class="number">5000</span>);

  qDebug() <span class="operator">&lt;</span><span class="operator">&lt;</span> <span class="string">&quot;Property value:&quot;</span> <span class="operator">&lt;</span><span class="operator">&lt;</span> object<span class="operator">-</span><span class="operator">&gt;</span>property(<span class="string">&quot;someNumber&quot;</span>)<span class="operator">.</span>toInt();
  object<span class="operator">-</span><span class="operator">&gt;</span>setProperty(<span class="string">&quot;someNumber&quot;</span><span class="operator">,</span> <span class="number">100</span>);

</pre>
<p>You should always use QObject::setProperty(), <a href="qqmlproperty.html">QQmlProperty</a> or QMetaProperty::write() to change a QML property value, to ensure the QML engine is made aware of the property change. For example, say you have a custom type <code>PushButton</code> with a <code>buttonText</code> property that internally reflects the value of a <code>m_buttonText</code> member variable. Modifying the member variable directly like this is not a good idea:</p>
<pre class="cpp">

  <span class="comment">//bad code</span>
  <span class="type"><a href="qqmlcomponent.html">QQmlComponent</a></span> component(engine<span class="operator">,</span> <span class="string">&quot;MyButton.qml&quot;</span>);
  PushButton <span class="operator">*</span>button <span class="operator">=</span> qobject_cast<span class="operator">&lt;</span>PushButton<span class="operator">*</span><span class="operator">&gt;</span>(component<span class="operator">.</span>create());
  button<span class="operator">-</span><span class="operator">&gt;</span>m_buttonText <span class="operator">=</span> <span class="string">&quot;Click me&quot;</span>;

</pre>
<p>Since the value is changed directly, this bypasses Qt's meta-object system and the QML engine is not made aware of the property change. This means property bindings to <code>buttonText</code> would not be updated, and any <code>onButtonTextChanged</code> handlers would not be called.</p>
<a name="invoking-qml-methods"></a>
<h3 id="invoking-qml-methods">Invoking QML Methods</h3>
<p>All QML methods are exposed to the meta-object system and can be called from C++ using QMetaObject::invokeMethod(). Method parameters and return values passed from QML are always translated into QVariant values in C++.</p>
<p>Here is a C++ application that calls a QML method using QMetaObject::invokeMethod():</p>
<div class="table"><table class="generic">
 <tr valign="top" class="odd"><td >QML</td><td ><pre class="qml">

  // MyItem.qml
  import QtQuick 2.0

  Item {
      function myQmlFunction(msg) {
          console.log("Got message:", msg)
          return "some return value"
      }
  }

</pre>
</td></tr>
<tr valign="top" class="even"><td >C++</td><td ><pre class="cpp">

  <span class="comment">// main.cpp</span>
  <span class="type"><a href="qqmlengine.html">QQmlEngine</a></span> engine;
  <span class="type"><a href="qqmlcomponent.html">QQmlComponent</a></span> component(<span class="operator">&amp;</span>engine<span class="operator">,</span> <span class="string">&quot;MyItem.qml&quot;</span>);
  <span class="type">QObject</span> <span class="operator">*</span>object <span class="operator">=</span> component<span class="operator">.</span>create();

  <span class="type">QVariant</span> returnedValue;
  <span class="type">QVariant</span> msg <span class="operator">=</span> <span class="string">&quot;Hello from C++&quot;</span>;
  <span class="type">QMetaObject</span><span class="operator">::</span>invokeMethod(object<span class="operator">,</span> <span class="string">&quot;myQmlFunction&quot;</span><span class="operator">,</span>
          Q_RETURN_ARG(<span class="type">QVariant</span><span class="operator">,</span> returnedValue)<span class="operator">,</span>
          Q_ARG(<span class="type">QVariant</span><span class="operator">,</span> msg));

  qDebug() <span class="operator">&lt;</span><span class="operator">&lt;</span> <span class="string">&quot;QML function returned:&quot;</span> <span class="operator">&lt;</span><span class="operator">&lt;</span> returnedValue<span class="operator">.</span>toString();
  <span class="keyword">delete</span> object;

</pre>
</td></tr>
</table></div>
<p>Notice the Q_RETURN_ARG() and Q_ARG() arguments for QMetaObject::invokeMethod() must be specified as QVariant types, as this is the generic data type used for QML method parameters and return values.</p>
<a name="connecting-to-qml-signals"></a>
<h3 id="connecting-to-qml-signals">Connecting to QML Signals</h3>
<p>All QML signals are automatically available to C++, and can be connected to using QObject::connect() like any ordinary Qt C++ signal. In return, any C++ signal can be received by a QML object using <a href="qtqml-syntax-signals.html">signal handlers</a>.</p>
<p>Here is a QML component with a signal named <code>qmlSignal</code> that is emitted with a string-type parameter. This signal is connected to a C++ object's slot using QObject::connect(), so that the <code>cppSlot()</code> method is called whenever the <code>qmlSignal</code> is emitted:</p>
<div class="table"><table class="generic">
 <tr valign="top" class="odd"><td ><pre class="qml">

  // MyItem.qml
  import QtQuick 2.0

  Item {
      id: item
      width: 100; height: 100

      signal qmlSignal(string msg)

      MouseArea {
          anchors.fill: parent
          onClicked: item.qmlSignal("Hello from QML")
      }
  }

</pre>
</td></tr>
<tr valign="top" class="even"><td ><pre class="cpp">

  <span class="keyword">class</span> MyClass : <span class="keyword">public</span> <span class="type">QObject</span>
  {
      Q_OBJECT
  <span class="keyword">public</span> <span class="keyword">slots</span>:
      <span class="type">void</span> cppSlot(<span class="keyword">const</span> <span class="type">QString</span> <span class="operator">&amp;</span>msg) {
          qDebug() <span class="operator">&lt;</span><span class="operator">&lt;</span> <span class="string">&quot;Called the C++ slot with message:&quot;</span> <span class="operator">&lt;</span><span class="operator">&lt;</span> msg;
      }
  };

  <span class="type">int</span> main(<span class="type">int</span> argc<span class="operator">,</span> <span class="type">char</span> <span class="operator">*</span>argv<span class="operator">[</span><span class="operator">]</span>) {
      <span class="type">QGuiApplication</span> app(argc<span class="operator">,</span> argv);

      <span class="type">QQuickView</span> view(<span class="type">QUrl</span><span class="operator">::</span>fromLocalFile(<span class="string">&quot;MyItem.qml&quot;</span>));
      <span class="type">QObject</span> <span class="operator">*</span>item <span class="operator">=</span> view<span class="operator">.</span>rootObject();

      MyClass myClass;
      <span class="type">QObject</span><span class="operator">::</span>connect(item<span class="operator">,</span> SIGNAL(qmlSignal(<span class="type">QString</span>))<span class="operator">,</span>
                       <span class="operator">&amp;</span>myClass<span class="operator">,</span> SLOT(cppSlot(<span class="type">QString</span>)));

      view<span class="operator">.</span>show();
      <span class="keyword">return</span> app<span class="operator">.</span>exec();
  }

</pre>
</td></tr>
</table></div>
<p>When a QML object type is used as a signal parameter, the parameter should use <a href="qml-var.html">var</a> as the type, and the value should be received in C++ using the QVariant type:</p>
<div class="table"><table class="generic">
 <tr valign="top" class="odd"><td ><pre class="qml">



</pre>
</td><td ><pre class="cpp">

  <span class="keyword">class</span> MyClass : <span class="keyword">public</span> <span class="type">QObject</span>
  {
      Q_OBJECT
  <span class="keyword">public</span> <span class="keyword">slots</span>:
      <span class="type">void</span> cppSlot(<span class="keyword">const</span> <span class="type">QVariant</span> <span class="operator">&amp;</span>v) {
         qDebug() <span class="operator">&lt;</span><span class="operator">&lt;</span> <span class="string">&quot;Called the C++ slot with value:&quot;</span> <span class="operator">&lt;</span><span class="operator">&lt;</span> v;

         <span class="type">QQuickItem</span> <span class="operator">*</span>item <span class="operator">=</span>
             qobject_cast<span class="operator">&lt;</span><span class="type">QQuickItem</span><span class="operator">*</span><span class="operator">&gt;</span>(v<span class="operator">.</span>value<span class="operator">&lt;</span><span class="type">QObject</span><span class="operator">*</span><span class="operator">&gt;</span>());
         qDebug() <span class="operator">&lt;</span><span class="operator">&lt;</span> <span class="string">&quot;Item dimensions:&quot;</span> <span class="operator">&lt;</span><span class="operator">&lt;</span> item<span class="operator">-</span><span class="operator">&gt;</span>width()
                  <span class="operator">&lt;</span><span class="operator">&lt;</span> item<span class="operator">-</span><span class="operator">&gt;</span>height();
      }
  };

  <span class="type">int</span> main(<span class="type">int</span> argc<span class="operator">,</span> <span class="type">char</span> <span class="operator">*</span>argv<span class="operator">[</span><span class="operator">]</span>) {
      <span class="type">QApplication</span> app(argc<span class="operator">,</span> argv);

      <span class="type">QQuickView</span> view(<span class="type">QUrl</span><span class="operator">::</span>fromLocalFile(<span class="string">&quot;MyItem.qml&quot;</span>));
      <span class="type">QObject</span> <span class="operator">*</span>item <span class="operator">=</span> view<span class="operator">.</span>rootObject();

      MyClass myClass;
      <span class="type">QObject</span><span class="operator">::</span>connect(item<span class="operator">,</span> SIGNAL(qmlSignal(<span class="type">QVariant</span>))<span class="operator">,</span>
                       <span class="operator">&amp;</span>myClass<span class="operator">,</span> SLOT(cppSlot(<span class="type">QVariant</span>)));

      view<span class="operator">.</span>show();
      <span class="keyword">return</span> app<span class="operator">.</span>exec();
  }

</pre>
</td></tr>
</table></div>
</div>
<!-- @@@qtqml-cppintegration-interactqmlfromcpp.html -->
        </div>
       </div>
   </div>
   </div>
</div>
<div class="footer">
   <p>
   <acronym title="Copyright">&copy;</acronym> 2019 The Qt Company Ltd.
   Documentation contributions included herein are the copyrights of
   their respective owners.<br/>    The documentation provided herein is licensed under the terms of the    <a href="http://www.gnu.org/licenses/fdl.html">GNU Free Documentation    License version 1.3</a> as published by the Free Software Foundation.<br/>    Qt and respective logos are trademarks of The Qt Company Ltd.     in Finland and/or other countries worldwide. All other trademarks are property
   of their respective owners. </p>
</div>
</body>
</html>