Written by Günter Schwann
2018/07/06
Basics of a nice QML file
What makes a QML file (often called component) a well written good quality one? Let’s take a look at example 1:
import QtQuick 2.9
MouseArea {
anchors.right: parent.right
anchors.bottom: parent.bottom
id: button
Rectangle {
anchors.fill: parent
color: "lightgray"
}
width: 100
height: 20
property string text: ""
Text {
anchors.centerIn: parent
text: button.text
}
function foo() {
}
}
And here almost the same as example 2:
import QtQuick 2.9
/**
Simple push button like component
No support for theming or icons are provided
*/
Item {
id: root
/// The text on the button
property alias text: textItem.text
/// The signal is emitted when the user clicked on the button
signal clicked()
implicitWidth: textItem.implicitWidth
implicitHeight: textItem.implicitHeight
width: implicitWidth
height: implicitHeight
Rectangle {
id: backround
anchors.fill: parent
color: "lightgray"
}
Text {
id: textItem
anchors.centerIn: parent
}
MouseArea {
id: clickArea
anchors.fill: parent
onClicked: {
root.clicked();
}
}
QtObject {
id: internal
function foo() {
}
}
}
I hope you agree that example 2 is a lot cleaner and easier to use. But let’s go through the list of differences:
- The QML files should always have the same structure. Starting with the public API like properties, signals and functions. Then the derived properties that it sets and then the items it contains. The idea is that if someone want’s to use that component, he only needs to look at the top part. And when you navigate through the code it’s a lot easier.
- The public API should be documented. Just like with any quality code.
- The main Item the file consists of, has “root” as its id. It’s the id that is usually used the most in the file. And it’s easier if you always use the same id.
- All items have an id set. I do this, as this gives a name to that item that describes what it is
- The id of an item is always in the first line.
- For the text property an alias is used to to save duplication, memory and binding effort.
- The main item should not be derived from any other component that it not really is. It should rather be only a composition. Therefore the good one is a pure Item, and only contains the Rectangle, Text and MouseArea.
- The implicit size is set and used as the default size. The implicit size is mostly used for dynamic layouts. The actual size can be overwritten when it’s used. But a sane default can be handy. In contrast, in the bad example the component already assumes on how it’s gonna be used – by setting anchors in this case.
- Properties and functions that should not be used from outside should be hidden. I do this by moving them to an QtObject that I name internal (for me that’s similar to d-pointers in Qt C++). So the function is called by “internal.foo()” instead of “root.foo()” or just “foo()”. Another option is to start the name of “private” properties and functions with a double underscore (would be __foo() here).
The example 2 is slightly more work. But as usual, quality code adds a bit extra effort. Which is not that much especially once one is used to it. So this short list covers already many aspects of a well written QML file that is easy to use. Following those ideas will help to generate reusable and more maintainable QML components.