Qt 5.12 LTS is out .Time to update your projects.

Qt 5.12 released
Qt 5.12 released

Qt 5.12 was released on December 6, 2018. This is a LTS(Long Term Supported version) of Qt which will be supported for a 3 year period time. The LTS version before that was Qt 5.9 ( released on May 31, 2017) and the one before that was Qt 5.6 (released on March 16, 2016) you get the idea. This means that Qt 5.6 will stop being supported by the Qt Company ( the guys behind Qt) somewhere in the first moths of 2019.

This article will highlight the new features and things to look out for when updating your Qt and QML projects to the latest version. Specifically for students from our various courses on Qt and QML. We tested the new version on the windows OS using the mingw compiler.

This new version introduces a lot of bug fixes and many new features that make the Qt framework generally better to work with .Some of the biggest highlights, relevant to our various courses on Qt are listed below

  • The Javascript engine was updated from ECMAScript 5 to support ES7; ECMAScript is the standard behind the Javascript language and version 7 introduces new features allowing you to use Javascript in a modern way.
  • TableView was added as another Item View component in Qt Quick. It’s something close to the ListView API, but makes representing tabular data very convenient. We’re working on a tutorial about that( should be out soon)
  • Various controls in Qt Quick Controls 2 gained new methods or new functionalities

There were also lots of other improvements in multiple modules of the C++ side of Qt. Another major step is that now Python is fully supported as a language you can use to write Qt cross platform applications. You can read more on the goodies of this new version on the official release blog post or the youtube video below about Qt5.12 release.

Qt 5.15 Release Video

If you are enrolled in one of our courses on Qt and particularly if it is your first time moving from one version of Qt to another, we do recommend to update to this new version of Qt. We went ahead and updated all the source code for the courses and updated our download and install lectures to highlight the version you should download.

On top of that, we added text lectures where you would need to be careful on the changes introduced by Qt 5.12. If in doubt, do download the updated source code for any lecture and take reference to that. But I felt it was a good idea to highlight what you need to be aware of and what to do specifically in your code here in one place. Let’s move on and look at that.

QML: Qt Quick and Qt Quick Controls Imports

Our courses on Qt Quick were recorded with the current version being Qt 5.11, so our typical qml file would look something like

import QtQuick 2.11
import QtQuick.Window 2.11
import QtQuick.Controls 2.4
import QtQuick.Layouts 1.3

Window {
    ...
}

Notice that QtQuick version was 2.11 and 2.4 for QtQuick Controls. A good piece of doc to look at to know how Qt Quick and QtQuick Controls versions match to your Qt version can be found from the official docs . From that doc page , you see that the rule for QtQuick Controls is kind of broken and that from Qt.5.11 to Qt 5.12, QtQuick Controls goes from 2.4 to 4.12. From the table in there, our code snippet above, if updated to Qt 5.12, it becomes like below

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.3

Window {
    ...
}

This looks simple and it is. The one point that can confuse some is that , for example, if you visit the documentation for some Qt Quick Controls 2 component, let’s say the Dial Control, the doc says that you should import QtQuick Controls 2.5.

import QtQuick Controls 2.5

This seems to conflict with what we saw in the table previously (import QtQuick Controls 2.12) ,but I have tested them both and they work pretty well. So it will be a matter of choice which one you choose to use.

Binding loops on the Dialog Component

When working with the dialog component coming from Qt Quick Controls like below,

Button {
           ...
            Dialog {
                id: contentDialog
                x: (parent.width - width) / 2
                y: (parent.height - height) / 2
                width: Math.min(parent.width, parent.height) / 3 * 2
                contentHeight: logo.height * 2
                .....
            }
}

you may see the warning about the binding loop on the implicitWidth or implicitHeight of the dialog. Something like below

qrc:/InputDialog.qml:15:5: QML Dialog: Binding loop detected for property "implicitWidth"

Binding loops are a problem that comes when you have properties that depend on each other in some kind of infinite loop. To give you some context, take a look at the snippet below

Rectangle  {
       id : mRect1
       width : mRect2.width
}

Rectangle  {
       id : mRect2
       width : mRect1.width
}

We have two rectangles. The width of the first rectangle depends on the width of the second, and the width of the second depends on the width of the first. So far this may look like there is nothing wrong. But when you set the width of one of the rectangles, lets say width = 300 for mRect1, mRect2 is going to detect the change in width for mRect1 ( because it’s width is bound to the width of mRect1 : width : mRect1.width) and it’s going to update its width to the new value.

But the width of mRect1 is also bound to the width of mRect2, so mRect1 is going to detect the change too and have to update its with. mRect2 is going to detect the change …. You get the idea. The QML engine is going to keep looping around setting widths for the two rectangles and it’s not going to stop until the application is stopped. You obviously don’t want this to happen as it’s a big waste on your resources. Qt Creator is is usually kind to us and when a binding loop is detected, we are warned with a warning like we saw above for the Dialog.

It is this same problem of binding loop that happens with with our Dialog code. The funny thing is, with Qt5.11 we didn’t have the this binding loop. And this a good chance for beginning Qt developers to experience that even though changes within one major version ( 5 here) don’t change the APIs significantly, some logic from your application may be affected(by the internal changes to Qt itself) and you should carefully test your code with new versions and adapt the code as necessary. In our case, if we play with our code and set the contentHeight of the dialog to a hard coded value like below

Button {
           ...
            Dialog {
                id: contentDialog
                x: (parent.width - width) / 2
                y: (parent.height - height) / 2
                width: Math.min(parent.width, parent.height) / 3 * 2
                contentHeight: 300
             
                .....
            }
   }

and run our app, you see that the warning about the binding loop goes away. But I really feel bad about hard coding values so let’s at least make the contentHeight depend on the height of the parent like below

Button {
           ...
            Dialog {
                id: contentDialog
                x: (parent.width - width) / 2
                y: (parent.height - height) / 2
                width: Math.min(parent.width, parent.height) / 3 * 2
                contentHeight: parent.height/2
             
                .....
            }
        }

This also doesn’t introduce the binding loop as well. Notice that we didn’t try and go deep and find where the binding loop is coming from. We used a trial and error process to try and isolate where the problem is coming from and came up with a work around. I am not very sure myself at the moment where this binding loop is coming from, especially that we didn’t touch on the implicitHeight property in our code. The problem is probably coming from how things are implemented deep down in the Qt libraries but the most important thing is to eliminate the problem and make our code run without any binding loop. Later when you’ve learnt enough we may have a chance to dig deep in the Qt source code and see how things are tied together.

Some C++ compiler warnings from Qt Creator

After updating to the Qt Creator version 4.8 that comes with Qt 5.12, we saw some warnings from Qt Creator that we didn’t see from previous versions and we need to address those as well. One we saw a couple of times is shown below

zero as null pointer constant warning

The nullability issue warning is saying that we shouldn’t use the NULL value today, as C++11 has introduced the nullptr keyword to signify the same.

The Conversion Issue warning is bringing to our attention that we are getting a long data type from the time() method and passing that as a parameter to the srand() method. We may loose on the precision on the number we get from the time() method. We get rid of the warning by using the nullptr keyword and explicitely casting the long value from the time() method to unsigned int that we pass to srand() as shown below

srand (static_cast<unsigned int>((time(nullptr))));

This warning surfaced every where we tried to generate random numbers using the rand() method from stdlib.h .

These are the main issues we came across while updating our source code from previous versions of Qt to Qt5.12. If you come across something we haven’t talked about here or have any problem updating your code, do share with us in the comments below. This covers what I had to share about the release of Qt 5.12 and what should be done to migrate your code to this new version. If you come across something we didn’t have a chance to touch on , we’d love to hear from you in the comments below. This is all from me today. Time to fire off the IDE and start hacking around.

Posted in C++, QML, Qt C++, Qt Quick and tagged , , .

One Comment

  1. I’m crashing with Qt 5.12 and the ExternalComponentSIgnalSlotDemo on Windows. winrt VS 2017 x64
    Seems to be the count property. If I don’t increment count it doesn’t crash

    rx::StateManager11::syncFramebuffer(1665): ! Assert failed in rx::StateManager11::syncFramebuffer(1665): framebuffer && !framebuffer->hasAnyDirtyBit() &&

Leave a Reply

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