Thinking Out of the Box

Multi-platform mobile software development: Qt instead of Xamarin

Jörg Preiß
Jörg Preiß
February 28th, 2017

Microsoft is accessing the field of WPF platform independence with Xamarin Forms. However, there has for a long time been an existing framework that runs on Windows, MacOS, Linux and starting with version 5 on iOS, Android, Sailfish OS and other operating systems – without re-implementation: Qt.

LISTING 1: MAIN.CPP

 

Qt has been around since 1992. For a long time, the company Trolltech distributed the framework commercially. There was a free version for the Linux desktop KDE that later was licensed under GPL. The two versions differed in the availability of certain modules. Starting with version 4.5 in 2009, the LGPL (GNU Lesser General Public License) was added. The current version 5.x is available in commercial and free versions as well. The rights are currently owned by The Qt Company.

Qt development was distinguished by the signal/slot principle. While other frameworks still used events, this already was an implementation of the publish-subscribe pattern. A button provides the clicked() signal, which view components can bind to a slot onClicked().

Version 4.7 introduced the Qt Markup Language, QML. While designers previously generated the completed source code, now the interface could be described in a JSON-like language. On-screen elements can be manipulated with JavaScript, values and lists can be bound. The framework achieved an architecture called model-view-delegate. Version 5.6 was used for this article.

First window

As in WPF logic and view are clearly separated through the use of different languages. The application is initialized by C++ code, as seen in listing 1. In the QQml engine, values can be registered in a QQmlContext and bound to. Generally everything that can be derived from QObject can also be registered. This way, the DataContext known from WPF can be implemented, for example with a controller like in listing 2.

Declared properties can be read inside the QML code. To make changes visible there as well, signals have be emitted when setting the values. Listing 3 clarifies the use of properties: text elements offer read access, TextInput also allows changes. The binding of the first variant sends the new text directly to the second TextInput. In the second variant the change is executed with a function call and needs no further bindings.

LISTING 2: MAINCONTROLLER.H

 

LISTING 3: MAIN.QML

 

Lists, filters, sorting

How about the handling of lists? In WPF, a ListBox is filled by an ItemsSource, its style is changed and the ListItem templates are customized. In QML, the list is filled according to a model and the style of the elements is described with a delegate.

There are multiple ways to present elements. The Highrise example uses a GridView for the multi-column display and a ListView for the master view. Another option which this article does not cover would be listing using a Repeater.

In the current example the list delegates are static. However they could just as well be computed by a JavaScript function. This for example allows a tile view that switches view depending on the window size.

Listing 4 renders the list of all rooms with their current status. A GridView is used because the list has two columns. Neither sorting nor filtering are needed so that a model can be used directly. That model is BuildingModel, a class derived from QAbstractListModel (listing 5).

The software accesses the different attributes of a ListItem through roles. To read and display the list, at least the functions data(), rowCount() and roleNames () must be overwritten. In the current model, the room status will be editable too, so the function setData() is overwritten as well. Here, the emission of the dataChanged signal at the end of the function is of note, because no change would be propagated without it.

Instead of specifying the attribute accesses by roles, the values can also be distributed to columns. In this case derive from QAbstractTableModel and distribute the attributes to columns. Corresponding examples can be found in the documentation.

The room list on the right is displayed in full. In contrast, the master view on the list should be filterable. As the data source is the same – all rooms – only a QSortFilterProxyModel is needed which in this case handles all the filtering out of unwanted elements. For this the function filterAcceptsRow() is overwritten. Building on that, overwriting lessThan() could enable sorting.

Listing 6 shows the advantage of registered elements within the QmlContext: the BuildingProxy has to be registered in the QmlContext, so the ListView can access it. Once it is registered, however, it can be accessed from everywhere. The automatisms in Qt trigger the update of affected windows.

LISTING 4: ROOMGRIDVIEW.QML

 

Keyboard controls

Focus is a frequently misunderstood concept regardless of framework. If I’m in an input field and press [Tab] I want to jump to the next input field. That is the simple case. But even the simple Highrise example already involves three different and actually simultaneously active focuses: the EditBox is the just mentioned input field. Additionally, there is a focused element that changes the rooms lighting status on a press of [Return] – analogous to a double click. Keys.onReturnPressed is responsible for this.

 

LISTING 5: BUILDINGMODEL.H

 

Likewise there is a focused element that in this case only serves as navigation. Each focus area in QML is enclosed in a FocusScope as can be seen in the files mentioned above. Within Highrise/BuildingView.qml all three areas are marked as accessible with activeFocusOnTab.

Custom Components

Strictly speaking, Highrise already uses multiple custom components: every QML file can be used as a type in another QML file, like in listing 4 and listing 6 for the two left and right views.

But all other files in Highrise/components were designed as independent controls too – the EditBox with embedded icon as well as the scrollbar. The more we work in Qt and QML the more we work without pre-made components like a button.

The look button can be influenced in a limited way by the style property. But by using Rectangles, MouseAreas and other basic elements, the usage of a component can be specified more precisely.

For example take a RangeSlider, a slider with a lower and upper value. Overlaying two sliders does not work. Instead we take a rectangle as the slider track, two rectangles as thumbs, each containing a MouseArea to make the thumbs touchable, and carry over the values with JavaScript code. Of course there is the possibility to implement custom controls in C++ and providing them inside QML.

LISTING 6: BUILDINGVIEW.QML

 

Animations

The potential of WPF is admittedly enormous with the use of storyboards, but not always easy to use. There are developers that use Blend just to configure the storyboard options.

QML provides a state machine here as well. In EditBox only one state is declared: when a text is entered the watermark icon disappears. When the new state is entered the specified properties are set. Conversely, when the state is left, the changes are undone. In this case the state is linked to a condition. But the state can also be changed by assigning state = “hasText”.

As simply hiding the icon would be too abrupt, it should be animated. Here we turn to transitions. They specify transitions in general, or from one state to another. In the transitions the different animation elements specify the type of animation. For example, there is OpacityAnimator, RotationAnimator or a general NumberAnimation. Animations can run simultaneously with ParallelAnimation or one after another with SequentialAnimation. The two types can also be nested.

Highrise

This example shows Highrise with a GridView and a ListView

Custom ressources

WPF developers are going to miss the possibility to outsource ressouces into RessourceDictionaries. It is simply bad style to repeat color definitions in every control. But there is help: the singleton modules. The first line of the according QML file is pragma Singleton, inside a QtObject with all properties is created. For a color singleton the colors.qml is

respectively for Fonts.qml:

Both files are registered as singleton modules and can be used in all other QML files:

Debugging

While in XAML the main problems are displayed in the console if they are displayed at all, in QML console.debug() in the JavaScript code is used. Problems can appear if bindings to models do not work or update signals are not emitted.

Here, maybe GammaRay can help. Similar to Snoop it shows the current tree, lists signals and linked slots, visualizes the state of the state machine and so on.

Fazit

QML and XAML have a lot in common. A signal in one language is a INotifyPropertyChanged.  Bindings and attached properties exist. It is considered poor style in both worlds to implement too much functionality in the markup.

But there are large differences as well. Because familiar WPF approaches like templating and resource dictionaries are missing, QT demands a different mindset. In return, the learning curve seems to be less steep overall. The enrichment of interface functionality with JavaScript is pleasant as well. Approaches like behaviours aren’t needed. Besides the mentioned platforms, the growing internet of things is missing. There is the option of booting a Qt-optimized software stack on devices. Time will tell if this option will stand its ground opposite Windows 10.

This article first appeared in dotnetpro

Want to know more about our services, products or our UX process?
We are looking forward to hearing from you.

Luzie Seeliger

Project Coordination and Communication

+49 681 959 3110

Contact form

  • Saarbrücken

    Science Park Saar, Saarbrücken

    South West Location

    Headquarter Saarbrücken
    Centigrade GmbH
    Science Park 2
    66123 Saarbrücken
    Germany
    Saarland
    On the map

    +49 681 959 3110

    +49 681 959 3119

  • Mülheim an der Ruhr

    Games Factory Mühlheim an der Ruhr

    North West Location

    Office Mülheim
    Centigrade GmbH
    Kreuzstraße 1-3
    45468 Mülheim an der Ruhr
    Germany
    North Rhine-Westphalia
    On the map

    +49 208 883 672 89

    +49 681 959 3119

  • Haar · Munich

    Haar / München

    South Location

    Office Munich
    Centigrade GmbH
    Bahnhofstraße 18
    85540 Haar · Munich
    Germany
    Bavaria
    On the map

    +49 89 20 96 95 94

    +49 681 959 3119

  • Frankfurt am Main

    Frankfurt am Main

    Central Location

    Office Frankfurt
    Centigrade GmbH
    Kaiserstraße 61
    60329 Frankfurt am Main
    Germany
    Hesse
    On the map

    +49 69 241 827 91

    +49 681 959 3119