Cross-Platform Development with Qt Quick and QML

Cross platform code has long been one of the holy grails of software development.  The long sought ability to write a single code base and compile for any given target platform promises to reduce duplicate development and to expand the market for a developed application. Logikos recently had an opportunity to work with a toolset that delivers on that promise: Qt Quick and QML.

As a cross-platform framework for application development, Qt runs on numerous platforms, including: Android, iOS, Linux, Windows, and Mac OS.  Qt Company is responsible for the proprietary version of Qt, and they work with other members of the Qt Project to maintain an open-source variant of the toolset.  Qt applications can be developed using open-source tools such as Eclipse, or using Qt’s own development environment, Qt Creator.

Although Qt provides cross-platform support for a variety of application needs (e.g. database and network access, XML and JSON parsing, and thread management), the primary purpose of Qt is to abstract user interface (UI) development across platforms.  The first versions of Qt mixed C++ application logic with UI definition.  But starting with Version 5.0, Qt introduced a modern, markup-based UI development framework called Qt Quick.  Qt Quick separated the C++ back end from the UI and introduced a markup language, QML, for the front end.  Developers create QML text files that are interpreted at run time by the Qt engine.  QML files can usually be moved between platforms and run without changes.

QML

QML is based on an implementation of Javascript.  A QML file is just a container for one or more components that might include a UI view, a partial view, a re-usable UI component, a master layout page, a data file or some combination of these.  To assist development, QML provides a set of built-in UI components like buttons or text areas, graphics elements and data and layout components such as the familiar grid, row and flow.   Components are rendered in a nested hierarchy based on their position in the file, but each element may be precisely styled and positioned.  QML pages stack and combine easily, and each QML file has low overhead, making it easy to create and destroy them as needed.  QML provides a JavaScript implementation for scripting behavior.  JavaScript may be inline or in separate files.

MVD

For application architecture, Qt Quick follows a familiar model-view-delegate design.  Models can be almost any ordered list of data, including JSON.  In addition, models can be defined in C++ classes and made available to the QML.  Qt Quick provides a variety of views such as ListView and GridView that bind to the model, while delegates provide input capabilities and specify how each data element will be rendered.

Signals and Slots

The main form of intra-application communication is a system of signals and slots, analogous to events and handlers.  A signal is essentially a name and a set of parameters.  The corresponding slot simply appends an “on” to the signal name and implicitly invokes a JavaScript callback to handle the signal. 

As in any UI, signals are commonly used to process user inputs, clicks, hover etc.  In addition, each property in a QML page has an associated signal that will be emitted when the property changes.  Each QML component in a composition has access to the signals emitted from the other components, and signals are easily chained between components.  QML exposes a simple mechanism for creating a slot for any signal emitted by any QML object at any place in the stack.

Application logic in custom C++ classes is easily exposed to QML and, again, the preferred communication method is slots and signals.  Because QML doesn’t have support for complex data types, the most convenient method to pass complex data is via JSON parameters.

Qt Quick and QML provide a flexible cross-platform development platform that embodies many contemporary best practices in UI development including separation of UI code using markup, JavaScript for UI behavior, and the model-view-delegate architecture pattern.  Try it out!


Qt Image Credit