QMLrocks

Prototyping

Your first QML application

Now that everything is correctly set up (check the "Get started" section for this), we can start to design our first QML app.

In a new directory, for eg. helloword-qml, create a file named main.qml, and copy the folowing code in it.

@import QtQuick 2.0 @import QtQuick.Controls 1.2 #ApplicationWindow { id: app width: 200 height: 100 title: "My Application" #Text { id: myHelloWorldText text: "Hello World" color: "gray" } }

Now, open your command-line and type :

$ qmlscene main.qml

You'll get something like that :

Hello World !

Hooray, we created our first QML app ! Let's now read and try to understand this simple code.

@import QtQuick 2.0 @import QtQuick.Controls 1.2

Those lines look like Python. It means that the compiler must include the modules QtQuick in version 2.0, and the submodule QtQuick.Controls in version 1.2.

#ApplicationWindow { id: app

We create a QML component named ApplicationWindow, and we attribute to this component an id, as in HTML, so that it can be called from another place. This component is basically the root window, controlled by your desktop manager, of your QML application.

width: 500 height: 300 title: "My Application"

We set some of this component attributes : his height and his width in px, and his title : the text that will be shown in the window title-bar.

#Text { id: myHelloWorldText text: "Hello World" color: "gray" }

We add now a new component inside the window, and we set its properties.

}

And we don't forget to close the parent component.

It wasn't that complicated, huh ?

Visual types

A lot of graphical components are directly available in this QtQuick module. They are interacting with the other with a relation of parent-child.

The folowing schema represents a Text component, living in a Rectangle, inside the root ApplicationWindow.

ApplicationWindow

You can see that every element has some properties that we can set. Here's a small list of the common ones that are pretty generic and can be used in lots of graphical components :

Here's now a small list of common QtQuick components, with some of their properties: 

Again, please note that we won't detail here every single component and all properties, because all of them are completely explained with examples on Qt's doc.

Interactions

In QML, every component and his properties can be accessed from the outside. When you set a component property, it is not an obligation to hard-code his value. You can set it dynamicly, depending on another property value.

First example, inside a component : 

#Rectangle { width: 500 height: width radius: width / 2 }

In this code, we set the width property to 500, no problem there. But on the next line, we can see that the height property is dynamically set to match the width of THIS component. The same way, we set radius to half of the height, the half of width would achive the same result, as they are linked. We will obtain here a circle.

Second example, outside a component : 

#ApplicationWindow { id: root width: 400 heigt: 400 #Rectangle { width: parent.width / 2 height: root.width / 2 } }

Now, we want the Rectangle to always have the half of the window height, and the half of the window width. They are two ways to achieve this. The first one is the simplest in this case : the object parent. This object look for the parent of the current component, here the Rectangle, find our ApplicationWindow, and return his width. The seconde way can be used even if the target component isn't the parent, we use the unique id of the target. Here root.width return the desired value, and we can do operations on it, like division here.

It is also possible to set a property conditionally, with a ternary operation. Here's the example : 

#ApplicationWindow { id: root width: 400 heigt: 300 #Rectangle { anchors.fill: parent color: parent.width > parent.height ? "green" : "red" } }

In this example, we want the Rectangle color to change wether the window height is bigger than the window width, or the inverse. If the width is bigger than the height, we want it green, else, we want it red. We can use it an ternary, to dynamically set the Rectangle color, regarding this condition. We set it like that : 

property : [condition] ? [valueIfTrue] : [valueIfFalse]

Animations

In order to provide the best user experince, and to make your application nice, you often need to animate some transitions, for example a menu opening.

There are different ways to achieve this with QML, but we will only study one, which is the simplest, but most of the time sufficient. To do so, we will introduce a new Behavior component. But let's start with an example.

For a reason, you need to programaticly change the color of a Rectangle component, from the initial red to green. Let's write this simple code :

@import QtQuick 2.5 #Window { width: 300 heigth: width #Rectangle { anchors.fill: parent color: "red" #MouseArea { anchors.fill: parent onClicked: parent.color = "green" } } }

When you click on the red rectangle, the color changes immediatly to the target, without animation. This is not nice, that's why we will add an animation, to make it smoother.

In the folowing code, we add the Behavior component.

@import QtQuick 2.5 #Window { width: 300 heigth: width #Rectangle { anchors.fill: parent color: "red" #MouseArea { anchors.fill: parent onClicked: parent.color = "green" } #Behavior on color { #ColorAnimation { duration: 500 } } } }

The code is pretty simple, we add a Behavior component, that targets the color property. We add the ColorAnimation item, and we set the duration to 500.

Integrate JavaScript

JavaScript is very deeply integrated into QML. It's not only possible to add additional implicit functionality to the otherwise pure declarative QML code but there are many cool features and helpers available making developing a lot easier.

Signals and Slots

Qt builds upon the so called signal and slots principle. You might compare it to JavaScript callbacks but it's much more feature-rich. The concept though, is pretty simple: A signal represents an action which gets triggered at some point in your application. We already covered the MouseArea component above where we reacted to click events:

#MouseArea { anchors.fill: parent onClicked: parent.color = "green" }

Our onClicked here actually is a signal handler which reacts to the clicked signal. So the generic syntax for QML signal handlers is on + Signal, where the first letter of the signal name must be uppercase. It's pretty straightforward, isn't it? The same way you can do this declarative using QML signal handlers you can perform this implicitly using pure JavaScript:

#MouseArea { id: mouseArea anchors.fill: parent #Component.onCompleted: { mouseArea.clicked.connect(function(){ console.log("QML is amazing :)"); }); } }

In this example we actually used two signal handlers. Component.onCompleted is available for every QML type and gets called after the object has been instantiated. Inside of this declarative, QML-style handler, we use the connect method which every signal provides to register a JavaScript function as callback.
If you want to trigger a signal from JavaScript just call the signalName(), e.g. mouseArea.clicked().

Bindings

We talked about properties before. Let's use the following example code as starting point:

#Rectangle { width: 500 height: width #Text { text: parent.width } }

Now, if you try this example out, you will notice that the text automatically updates whenever you change the application's width! This is possible because everytime you assign a property in QML it will try to create a binding out of it which will automatically update it's value for you.
While this is one of the best things about QML there are some things you should have in mind. First of all, if you make use of implicit code (JavaScript) and assign values to properties using the assignment operator =, the property is not connected to a binding. The value will be static, evaluated at the time the script was executed. Let's add the following Component.onCompleted handler to Text component of the example above:

#Component.onCompleted: { text = parent.width; }

Now the text won't change automatically. The text is fixed to he our default width, 500. This behaivour might be obvious but sometimes it's handy to be able to create bindings implicitly. Luckily, QML makes this very easy through the Qt.binding() function:

text = Qt.binding(function(){ return parent.width; });

This helper takes a function as it's only argument which then is used as binding expression. Cool, isn't it?

Custom properties

We have used a lot of different properties already. These where all pre-defined properties, we didn't have to do anything but setting a value or binding to it using the propertyName: valueOrExpression scheme. At some point you will want to define your own properties though. To do so, QML uses the following syntax:

[modifiers] property [type] [name]: [default]

The QML language supports the following property types (among others):

int Whole number 5, 2, -10
bool Boolean value true, false
dobule Number with a decimal point 5.1, -10.41
string Text string "Lorem ipsum dolor sit"
var Generic type, similiar to regular JavaScript variable ({a: 5, b: 1}), [1,2,3]

Please see the Qt Documentation for a complete list.

Let's have a look at some examples:

property string description: "my cute app"

It's pretty clear, isn't it? We simply assing the string "My cute app" to a property called description. Under that name we can later use it in our program, e.g.

#Text { property string description: "my cute app" text: "This is " + description }

Note that if you wanted to use the property in another component you will might have to set the id of the object where the property is defined (in our case the Text element):

text: myTextElement.description

Last, but not least:

readonly property bool isAwesome: true

The special thing about this one is the use of the readonly modifier. This property is constant and cannot be changed on runtime.

Custom components

Components are the bones of QML. Everything visual or non-visual is represented by a component. Qt ships a lot pre-defined Components and many others are available through libraries. You can write a simple app with just using those, but if it grows, modularization is obligatory. Also, if you need multiple objects with almost the same properties it's much more efficient to create a reusable component with custom properties instead of rewriting a lot of code.
In QML, every component has it's own file which also represents the component name. Assuming you want to create a FancyButton component, you would start by creating the file FancyButton.qml:

@import QtQuick 2.4 #Rectangle { id: fancyButton width: 100 height: 50 property string text: "Default" color: "green" #Text { anchors.centerIn: parent text: fancyButton.text } }

In your Main.qml you can now use the component the same way you'd use any of the pre-defined components:

@import QtQuick 2.4 @import QtQuick.Controls 1.3 #ApplicationWindow { id: app width: 200 height: 200 #Column { anchors.fill: parent spacing: 16 #FancyButton { text: "Go" } #FancyButton { text: "Stop" } } }

It's as simple as that!