Qt QML Hot Tips #2
Mike Trahearn - Qt QML Hot Tips

Qt QML Hot Tips #2


Welcome to Part 2!

Continuing on a theme of raging against the tide of poorly written QML using examples from years of swooning over such elegantly and thoughtfully written mistakes...

Get your Property in Order!

Continuing on the theme of properties, a brief word on their declarations in C++. For C++ only Qt projects, you may only use them for e.g. some kind of RTTI, an abstraction for serialisation or just a mere convenience in Qt Creator's editor for generating all the getters and setters for you - which, by the way is a very nice feature.

But for QML projects using such C++ classes we need to take a bit more care...

QML Bindings

Of course you can't go far with QML without coming across bindings. They come in a variety of flavours from simple property assignments to relational couplings to other properties to function return values and many other exotic cases.

Let's take an example:

import QtQuick.Window // no version numbers needed since Qt 5.1

import My.Theme

Window {

?id: window

?width: 640

?height: 480

?visible: true

?color: MyTheme.backgroundColor

?Image {

???id: background

???width: window.width

???height: window.height

???source: Qt.resolvedUrl("semi-transparent-background.png")

?}

}        

(Notwithstanding this is a contrived example since you could use QtQuick.Controls' ApplicationWindow and set the background delegate to the Image and you can forget the sizing as it is done for you or even with the above you could use anchors), you'll notice the two binding expressions for width and height in the background Image.

Similar to signals and slots in C++ the Window has a height and a width property declared in its C++ backend class which, while having setters and getters, also signals emitted for the change notifications. This causes in turn the Image's width and height property bindings to be re-evaluated automatically and its width and height properties written to accordingly. This obviously updates the Image size.

You'll also notice the window's color (its fill color) is bound to what is called a singleton and is imported by the shown import statement. How to do this is not covered here, but suffice to say that MyTheme.backgroundColor property has a fixed color value and doesn't ever change.

The Golden C++ Property Rules for QML usage

These rules will help you create well formed and well behaved properties for QML use - but also C++ too!

1) All C++ Q_PROPERTYs that may change their value that published to QML MUST have a NOTIFY signal so that any binding expression depending on it will be correctly re-evaluated when it changes. Note that this still applies even in the property is readonly from QML.

2) Q_PROPERTY setter methods should be declared as slots so that the C++ method is available for the QML engine to call.

Note: Normally this is the case, but setters as slots may not always be necessary if you don't need an imperative way to modify a member variable and you actively want to remove that option e.g. if you are just doing simple assignments or bindings. However there are many valid reasons in both QML and C++ (some obscure) where setters as slots are absolutely necessary. Consider your requirements case by case.

3) All C++ Q_PROPERTYs that do not change their value must be declared CONSTANT. This tells the QML Engine that it shouldn't change and will allow you to use it in bindings even without the NOTIFY signal which is not necessary in this case.

The QML Engine will issue a warning at runtime warning if the rules it requires are not followed.

4) The FINAL keyword should be added to ensure that the compiler can spot if a Q_PROPERTY is being overwritten. Note that in future versions of Qt and also in the current Qt for MCUs (Qt Quick UltraLite) this is already enforced and will be essential in future optimisation and performance of the QML runtime and the QML compiler.

5) The property setter shall NOT modify the incoming value such that the value returned from the READ function would different. This is a bit more subtle but can be summarised as:

"What you put in should be the same as what you get out"

A good example is with Qt 5.15 where a QUrl property setter method may have a relative url value resolved to the setting QML context's baseUrl. Or, in a real use case I saw it was deemed perfectly fine to take an absolute url (e.g. a web server) address with a hostname and internally resolve the host to an IP address. In both cases it rendered the url seen inside the setter method as actually different to that which was actually set, and in both cases the NOTIFY signal was not emitted. So not only do we have a different value on the property than as set should it every be read, but we never actually got to be told about it.

Qt 6 now drops this implicit url resolution with QUrl properties as described here:

But if you still need the old behaviour you can set the QML_COMPAT_RESOLVE_URLS_ON_ASSIGNMENT environment variable.

Summary

Take care of your property investments!

要查看或添加评论,请登录

Mike Trahearn的更多文章

  • Qt QML Hot Tips #9

    Qt QML Hot Tips #9

    Part 9 - Move your QML over to the DARK side..

    11 条评论
  • #QtStories - My Experience. My Story. Your Future!

    #QtStories - My Experience. My Story. Your Future!

    The letters 'Q' and 't' have been at the core of my career and I would like to take a couple of moments to explain why.…

    6 条评论
  • Qt QML Hot Tips #8

    Qt QML Hot Tips #8

    Part 8 - How to save face by using namespaces - a quick guide to QML and enums! Following a rather extended period…

  • Qt QML Hot Tips #7

    Qt QML Hot Tips #7

    Part 7 - Does my RCC look BIG in this? Or, "How to handle your large assets"..

    1 条评论
  • Qt QML Hot Tips #6

    Qt QML Hot Tips #6

    Part 6 - The "Unbinding" Like sounding like a potential horror film title, this article is inspired by a shuddering…

    1 条评论
  • Qt QML Festive Hot Tips

    Qt QML Festive Hot Tips

    Ho Ho Hot Tips - Christmas Special! While your projects are getting stuffed and your turkey is still compiling I…

  • Qt QML Hot Tips #5

    Qt QML Hot Tips #5

    Part 5 - I'm sorry, your access is restricted! From Qt 5.15 and much more strictly in Qt 6, a series of improvements…

  • Qt QML Hot Tips #4

    Qt QML Hot Tips #4

    Part 4 - May I See Your ID? In this article I cover one of the easiest parts of the QML syntax - but its inclusion in…

    3 条评论
  • Qt QML Hot Tips #3

    Qt QML Hot Tips #3

    Part 3 - Are your properties required? if(someObjectProperty !== null) someObjectProperty.callFunction() is found…

    6 条评论
  • Qt QML Hot Tips #1

    Qt QML Hot Tips #1

    Welcome! This is the first of many extremely short articles containing some absolute nuggets of gold stashed away until…

    12 条评论

社区洞察

其他会员也浏览了