Sophie

Sophie

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

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" />
<!-- qtquick-bestpractices.qdoc -->
  <title>Best Practices for QML and Qt Quick | Qt Quick 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="qtquick-index.html">Qt Quick</a></td><td >Best Practices for QML and Qt Quick</td></tr></table><table class="buildversion"><tr>
<td id="buildversion" width="100%" align="right"><a href="qtquick-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="#custom-ui-controls">Custom UI Controls</a></li>
<li class="level2"><a href="#related-information">Related Information</a></li>
<li class="level1"><a href="#coding-conventions">Coding Conventions</a></li>
<li class="level1"><a href="#bundle-application-resources">Bundle Application Resources</a></li>
<li class="level2"><a href="#related-information">Related Information</a></li>
<li class="level1"><a href="#separate-ui-from-logic">Separate UI from Logic</a></li>
<li class="level2"><a href="#interacting-with-qml-from-c">Interacting with QML from C++</a></li>
<li class="level2"><a href="#related-information">Related Information</a></li>
<li class="level1"><a href="#using-qt-quick-layouts">Using Qt Quick Layouts</a></li>
<li class="level2"><a href="#dos">Dos</a></li>
<li class="level2"><a href="#don-ts">Don'ts</a></li>
<li class="level2"><a href="#related-information">Related Information</a></li>
<li class="level1"><a href="#type-safety">Type Safety</a></li>
<li class="level1"><a href="#performance">Performance</a></li>
<li class="level1"><a href="#tools-and-utilities">Tools and Utilities</a></li>
<li class="level1"><a href="#scene-graph">Scene Graph</a></li>
<li class="level1"><a href="#scalable-user-interfaces">Scalable User Interfaces</a></li>
<li class="level2"><a href="#related-information">Related Information</a></li>
</ul>
</div>
<div class="sidebar-content" id="sidebar-content"></div></div>
<h1 class="title">Best Practices for QML and Qt Quick</h1>
<span class="subtitle"></span>
<!-- $$$qtquick-bestpractices.html-description -->
<div class="descr"> <a name="details"></a>
<p>Despite all of the benefits that QML and Qt Quick offer, they can be challenging in certain situations. The following sections elaborate on some of the best practices that will help you get better results when developing applications.</p>
<a name="custom-ui-controls"></a>
<h2 id="custom-ui-controls">Custom UI Controls</h2>
<p>A fluid and modern UI is key for any application's success in today's world, and that's where QML makes so much sense for a designer or developer. Qt offers the most basic UI controls that are necessary to create a fluid and modern-looking UI. It is recommended to browse this list of UI controls before creating your own custom UI control.</p>
<p>Besides these basic UI controls offered by Qt Quick itself, a rich set of UI controls are also available with Qt Quick Controls 2. They cater to the most common use cases without any change, and offer a lot more possibilities with their customization options. In particular, Qt Quick Controls 2 provides styling options that align with the latest UI design trends. If these UI controls do not satisfy your application's needs, only then it is recommended to create a custom control.</p>
<a name="related-information"></a>
<h3 id="related-information">Related Information</h3>
<ul>
<li>Qt Quick Controls 2</li>
<li><a href="qtquick-index.html">Qt Quick</a></li>
</ul>
<a name="coding-conventions"></a>
<h2 id="coding-conventions">Coding Conventions</h2>
<p>See QML Coding Conventions.</p>
<a name="bundle-application-resources"></a>
<h2 id="bundle-application-resources">Bundle Application Resources</h2>
<p>Most applications depend on resources such as images and icons to provide a rich user experience. It can often be a challenge to make these resources available to the application regardless of the target OS. Most popular OS-es employ stricter security policies that restrict access to the file system, making it harder to load these resources. As an alternative, Qt offers its own resource system that is built into the application binary, enabling access to the application's resources regardless of the target OS.</p>
<p>For example, consider the following project directory structure:</p>
<pre class="cpp plain">

  project
  ├── images
  │   ├── image1.png
  │   └── image2.png
  ├── project.pro
  └── qml
      └── main.qml

</pre>
<p>The following entry in <code>project.pro</code> ensures that the resources are built into the application binary, making them available when needed:</p>
<pre class="cpp plain">

  RESOURCES += \
      qml/main.qml \
      images/image1.png \
      images/image2.png

</pre>
<p>A more convenient approach is to use the wildcard syntax to select several files at once:</p>
<pre class="cpp plain">

  RESOURCES += \
      $$files(qml/*.qml) \
      $$files(images/*.png)

</pre>
<p>This approach is convenient for applications that depend on a limited number of resources. However, whenever a new file is added to <code>RESOURCES</code> using this approach, it causes <i>all</i> of the other files in <code>RESOURCES</code> to be recompiled as well. This can be inefficient, especially for large sets of files. In this case, a better approach is to separate each type of resource into its own .qrc file. For example, the snippet above could be changed to the following:</p>
<pre class="cpp plain">

  qml.files = $$files(*.qml)
  qml.prefix = /qml
  RESOURCES += qml

  images.files = $$files(*.png)
  images.prefix = /images
  RESOURCES += images

</pre>
<p>Now, whenever a QML file is changed, only the QML files have to be recompiled.</p>
<p>Sometimes it can be necessary to have more control over the path for a specific file managed by the resource system. For example, if we wanted to give <code>image2.png</code> an alias, we would need to switch to an explicit <code>.qrc</code> file. Creating Resource Files explains how to do this in detail.</p>
<a name="related-information"></a>
<h3 id="related-information">Related Information</h3>
<ul>
<li>The Qt Resource System</li>
</ul>
<a name="separate-ui-from-logic"></a>
<h2 id="separate-ui-from-logic">Separate UI from Logic</h2>
<p>One of the key goals that most application developers want to achieve is to create a maintainable application. One of the ways to achieve this goal is to separate the user interface from the business logic. The following are a few reasons why an application's UI should be written in QML:</p>
<ul>
<li>Declarative languages are strongly suited for defining UIs.</li>
<li>QML code is simpler to write, as it is less verbose than C++, and is not strongly typed. This also results in it being an excellent language to prototype in, a quality that is vital when collaborating with designers, for example.</li>
<li>JavaScript can easily be used in QML to respond to events.</li>
</ul>
<p>Being a strongly typed language, C++ is best suited for an application's logic. Typically, such code performs tasks such as complex calculations or data processing, which are faster in C++ than QML.</p>
<p>Qt offers various approaches to integrate QML and C++ code in an application. A typical use case is displaying a list of data in a user interface. If the data set is static, simple, and/or small, a model written in QML can be sufficient.</p>
<p>The following snippet demonstrates examples of models written in QML:</p>
<pre class="qml">



</pre>
<p>Use <a href="qtquick-modelviewsdata-cppmodels.html#qabstractitemmodel-subclass">C++</a> for dynamic data sets that are large or frequently modified.</p>
<a name="interacting-with-qml-from-c"></a>
<h3 id="interacting-with-qml-from-c">Interacting with QML from C++</h3>
<p>Although Qt enables you to manipulate QML from C++, it is not recommended to do so. To explain why, let's take a look at a simplified example.</p>
<a name="pulling-references-from-qml"></a>
<h4 id="pulling-references-from-qml">Pulling References from QML</h4>
<p>Suppose we were writing the UI for a settings page:</p>
<pre class="qml">



</pre>
<p>We want the button to do something in C++ when it is clicked. We know objects in QML can emit change signals just like they can in C++, so we give the button an objectName so that we can find it from C++:</p>
<pre class="qml">



</pre>
<p>Then, in C++, we find that object and connect to its change signal:</p>
<pre class="cpp">

  <span class="preprocessor">#include &lt;QGuiApplication&gt;</span>
  <span class="preprocessor">#include &lt;QQmlApplicationEngine&gt;</span>
  <span class="preprocessor">#include &lt;QSettings&gt;</span>

  <span class="keyword">class</span> Backend : <span class="keyword">public</span> <span class="type">QObject</span>
  {
      Q_OBJECT

  <span class="keyword">public</span>:
      Backend() {}

  <span class="keyword">public</span> <span class="keyword">slots</span>:
      <span class="type">void</span> restoreDefaults() {
          settings<span class="operator">.</span>setValue(<span class="string">&quot;loadLastProject&quot;</span><span class="operator">,</span> <span class="type">QVariant</span>(<span class="keyword">false</span>));
      }

  <span class="keyword">private</span>:
      <span class="type">QSettings</span> settings;
  };

  <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">QQmlApplicationEngine</span> engine;
      engine<span class="operator">.</span>load(<span class="type">QUrl</span>(<span class="type">QStringLiteral</span>(<span class="string">&quot;qrc:/main.qml&quot;</span>)));
      <span class="keyword">if</span> (engine<span class="operator">.</span>rootObjects()<span class="operator">.</span>isEmpty())
          <span class="keyword">return</span> <span class="operator">-</span><span class="number">1</span>;

      Backend backend;

      <span class="type">QObject</span> <span class="operator">*</span>rootObject <span class="operator">=</span> engine<span class="operator">.</span>rootObjects()<span class="operator">.</span>first();
      <span class="type">QObject</span> <span class="operator">*</span>restoreDefaultsButton <span class="operator">=</span> rootObject<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;restoreDefaultsButton&quot;</span>);
      <span class="type">QObject</span><span class="operator">::</span>connect(restoreDefaultsButton<span class="operator">,</span> SIGNAL(clicked())<span class="operator">,</span>
          <span class="operator">&amp;</span>backend<span class="operator">,</span> SLOT(restoreDefaults()));

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

  <span class="preprocessor">#include &quot;main.moc&quot;</span>

</pre>
<p>With this approach, references to objects are &quot;pulled&quot; from QML. The problem with this is that the C++ logic layer depends on the QML presentation layer. If we were to refactor the QML in such a way that the <code>objectName</code> changes, or some other change breaks the ability for the C++ to find the QML object, our workflow becomes much more complicated and tedious.</p>
<a name="pushing-references-to-qml"></a>
<h4 id="pushing-references-to-qml">Pushing References to QML</h4>
<p>Refactoring QML is a lot easier than refactoring C++, so in order to make maintenance pain-free, we should strive to keep C++ types unaware of QML as much as possible. This can be achieved by &quot;pushing&quot; references to C++ types into QML:</p>
<pre class="cpp">

  <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);

      Backend backend;

      <span class="type">QQmlApplicationEngine</span> engine;
      engine<span class="operator">.</span>rootContext()<span class="operator">-</span><span class="operator">&gt;</span>setContextProperty(<span class="string">&quot;backend&quot;</span><span class="operator">,</span> <span class="operator">&amp;</span>backend);
      engine<span class="operator">.</span>load(<span class="type">QUrl</span>(<span class="type">QStringLiteral</span>(<span class="string">&quot;qrc:/main.qml&quot;</span>)));
      <span class="keyword">if</span> (engine<span class="operator">.</span>rootObjects()<span class="operator">.</span>isEmpty())
          <span class="keyword">return</span> <span class="operator">-</span><span class="number">1</span>;

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

</pre>
<p>The QML then calls the C++ slot directly:</p>
<pre class="qml">



</pre>
<p>With this approach, the C++ remains unchanged in the event that the QML needs to be refactored in the future.</p>
<p>In the example above, we set a context property on the root context to expose the C++ object to QML. This means that the property is available to every component loaded by the engine. Context properties are useful for objects that must be available as soon as the QML is loaded and cannot be instantiated in QML.</p>
<p>For a quick guide to choosing the correct approach to expose C++ types to QML, see Choosing the Correct Integration Method Between C++ and QML.</p>
<a name="related-information"></a>
<h3 id="related-information">Related Information</h3>
<ul>
<li>Integrating QML and C++</li>
<li>Chat application tutorial</li>
</ul>
<a name="using-qt-quick-layouts"></a>
<h2 id="using-qt-quick-layouts">Using Qt Quick Layouts</h2>
<p>Qt offers Qt Quick Layouts to arrange Qt Quick items visually in a layout. Unlike its alternative, the item positioners, the Qt Quick Layouts can also resize its children on window resize. Although Qt Quick Layouts are often the desired choice for most use cases, the following <i>dos</i> and <i>don'ts</i> must be considered while using them:</p>
<a name="dos"></a>
<h3 id="dos">Dos</h3>
<ul>
<li>Use <a href="qml-qtquick-item.html#anchors-prop">anchors</a> or the <a href="qml-qtquick-item.html#width-prop">width</a> and <a href="qml-qtquick-item.html#height-prop">height</a> properties to specify the size of the layout against its non-layout parent item.</li>
<li>Use the <a href="qml-qtquick-layouts-layout.html">Layout</a> attached property to set the size and alignment attributes of the layout's immediate children.</li>
</ul>
<a name="don-ts"></a>
<h3 id="don-ts">Don'ts</h3>
<ul>
<li>Do not define preferred sizes for items that provide implicitWidth and implicitHeight, unless their implicit sizes are not satisfactory.</li>
<li>Do not use anchors on an item that is an immediate child of a layout. Instead, use <code>Layout.preferredWidth</code> and <code>Layout.preferredHeight</code>:<pre class="qml">

  RowLayout {
      id: layout
      anchors.fill: parent
      spacing: 6
      Rectangle {
          color: 'azure'
          Layout.fillWidth: true
          Layout.minimumWidth: 50
          Layout.preferredWidth: 100
          Layout.maximumWidth: 300
          Layout.minimumHeight: 150
          Text {
              anchors.centerIn: parent
              text: parent.width + 'x' + parent.height
          }
      }
      Rectangle {
          color: 'plum'
          Layout.fillWidth: true
          Layout.minimumWidth: 100
          Layout.preferredWidth: 200
          Layout.preferredHeight: 100
          Text {
              anchors.centerIn: parent
              text: parent.width + 'x' + parent.height
          }
      }
  }

</pre>
</li>
</ul>
<p><b>Note: </b>Layouts and anchors are both types of objects that take more memory and instantiation time. Avoid using them (especially in list and table delegates, and styles for controls) when simple bindings to x, y, width, and height properties are enough.</p><a name="related-information"></a>
<h3 id="related-information">Related Information</h3>
<ul>
<li><a href="qtquick-positioning-layouts.html">Item Positioners</a></li>
<li><a href="qtquicklayouts-overview.html">Qt Quick Layouts Overview</a></li>
</ul>
<a name="type-safety"></a>
<h2 id="type-safety">Type Safety</h2>
<p>When declaring properties in QML, it's easy and convenient to use the &quot;var&quot; type:</p>
<pre class="cpp">

  property var name
  property var size
  property var optionsMenu

</pre>
<p>However, this approach has several disadvantages:</p>
<ul>
<li>If a value with the wrong type is assigned, the error reported will point to the location of the property declaration, as opposed to the location where the property was assigned to. This slows down the development process by making it more difficult to track down errors.</li>
<li>Static anaylsis to catch errors like the ones mentioned above is not possible.</li>
<li>The actual underlying type of the property is not always immediately clear to the reader.</li>
</ul>
<p>Instead, always use the actual type where possible:</p>
<pre class="cpp">

  property string name
  property <span class="type">int</span> size
  property MyMenu optionsMenu

</pre>
<a name="performance"></a>
<h2 id="performance">Performance</h2>
<p>For information on performance in QML and Qt Quick, see Performance Considerations And Suggestions.</p>
<a name="tools-and-utilities"></a>
<h2 id="tools-and-utilities">Tools and Utilities</h2>
<p>For information on useful tools and utilies that make working with QML and Qt Quick easier, see <a href="qtquick-tools-and-utilities.html">Qt Quick Tools and Utilities</a>.</p>
<a name="scene-graph"></a>
<h2 id="scene-graph">Scene Graph</h2>
<p>For information on Qt Quick's scene graph, see <a href="qtquick-visualcanvas-scenegraph.html">Qt Quick Scene Graph</a>.</p>
<a name="scalable-user-interfaces"></a>
<h2 id="scalable-user-interfaces">Scalable User Interfaces</h2>
<p>As display resolutions improve, a scalable application UI becomes more and more important. One of the approaches to achieve this is to maintain several copies of the UI for different screen resolutions, and load the appropriate one depending on the available resolution. Although this works pretty well, it adds to the maintenance overhead.</p>
<p>Qt offers a better solution to this problem and recommends the application developers to follow these tips:</p>
<ul>
<li>Use anchors or the Qt Quick Layouts module to lay out the visual items.</li>
<li>Do not specify explicit width and height for a visual item.</li>
<li>Provide UI resources such as images and icons for each display resolution that your application supports. The Qt Quick Controls 2 gallery example demonstrates this well by providing the <code>qt-logo.png</code> for <code>@2x</code>, <code>@3x</code>, and <code>@4x</code> resolutions, enabling the application to cater to high resolution displays. Qt automatically chooses the appropriate image that is suitable for the given display, provided the high DPI scaling feature is explicitly enabled.</li>
<li>Use SVG images for small icons. While larger SVGs can be slow to render, small ones work well. Vector images avoid the need to provide several versions of an image, as is necessary with bitmap images.</li>
<li>Use font-based icons, such as Font Awesome. These scale to any display resolution, and also allow colorization. The Qt Quick Controls 2 Text Editor example demonstrates this well.</li>
</ul>
<p>With this in place, your application's UI should scale depending on the display resolution on offer.</p>
<p class="centerAlign"><img src="images/qtquickcontrols2-gallery-welcome.png" alt="" /></p><a name="related-information"></a>
<h3 id="related-information">Related Information</h3>
<ul>
<li>Gallery example</li>
<li>Text Editor example</li>
<li>Font Awesome</li>
<li>Scalability</li>
<li>High DPI Displays</li>
</ul>
</div>
<!-- @@@qtquick-bestpractices.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>