I love Qt Quick, and yet…

I love Qt Quick. So much so that I probably cannot evaluate it very objectively. Qt Quick UI toolkit was great when it initially came out in 2010, and while lately there has been renewed focus on improving the toolkit, ultimately the core offering hasn’t evolved much in recent years. After Digia purchased Qt seems that the focus shifted back to its multi-platform roots, focusing on covering more OS ground instead of making substantial improvements to the toolkit’s capabilities. Which is a shame since Qt Quick has a lot of untapped potential. It is already a solid choice for device makers looking for a versatile embedded graphic environment. Qt wants to be a desirable cross-platform framework for companies making mobile and desktop applications, but as far as I know not that many top 100 App Store or Google Play applications are running Qt Quick. Also it never became easy enough to be widely adopted by the designers. There are still too many hoops to jump if you are not familiar with the underlying Qt framework.

I wish Qt Quick was easier for beginners, and could even work as a visual sketchbook for the students and artists playing around with interactive graphics and learning programming. I wish there were more innovative spearhead projects built with Qt. I wish Qt Quick had a demo reel that surpassed the ones from Kanzi UI, Open Frameworks, Processing, even the old TAT Cascades. I wish Qt had a lively innovation ecosystem swarming with hackers, tinkerers and designers not afraid to challenge the status quo.

In the last few years Qt Declarative module has seen improvements in QML language, graphics architecture and performance in expense of progress in Qt Quick itself and the overall UI development experience. This is unfortunate, and to me feels like many design prototyping tools like Processing, Zing Studio and Noodl hold more innovation potential, and better glimpse of what the future of UI development will be like.

The first step to reinvigorate ecosystem is to lower the barriers of innovation. Things that are easy to do have a potential to become available in abundance. To excel in UX and product building Qt needs seamless live design and coding environments, more visual primitives, better typography, grow Qt Quick Controls into a comprehensive UX pattern toolkit, lower performance footprint, better touch handling and models architecture.

Low-level components

Qt Quick Controls project provides basic components for creating user interfaces. Unfortunately basic components are not enough, to better empower application developers the whole abstraction level needs to be raised one step higher. Application developers don’t struggle with simple components like buttons and menus, they struggle integrating complex components like Web, Map, Video and Camera elements (both plain and chromed) into their apps and constructing comprehensive UX patterns spanning multiple views: for example how to implement a end-to-end sign in flow with all the bells and whistles that go with good UX, how to implement proper empty state handling and in-app tutorials for the application, how should a new feature be introduced and advertised to the user, how to combine different patterns like search and multi-selection in one coherent view, how to implement error handling across the application in a cross-platform manner, and so on.

Slow to iterate

Modify, deploy and run cycle of Qt apps could be greatly improved. Announcement of QML Live reloader environment sounds promising, but it is still quite far from web browser development tools that allow real-time property tuning, and various hover-on visualisations on top of the layouts and code. Prototyping tools like Noodl and Zing naturally go even further.

Large footprint

I was happy to read about Qt Lite project. Qt can be resource hungry. Last time I checked an empty Qt Quick process took around 10MB of dirty memory, a real application that imports different modules multiplies of that. QML Compiler helps a bit, but in general there is just too much cruft that gets loaded by the framework. You cannot start a Qt application quickly without boosters that pre-load a stub process in memory before the actual launch happens. And you cannot use boosters without OS-level support so cross-platform Qt apps running on iOS and Android are out of luck.

Unintuitive touch

Give a toddler an iPad and she can immediately interact with it. Give a toddler a Qt embedded device and she starts to struggle. The whole user interfaces freezes when she enthusiastically holds the screen with multiple fingers, because Qt cannot normally handle multiple simultaneous touch actions at a time. Even a tiny slice of thumb accidentally touching a screen edge renders all the buttons on the screen disabled. Qt multi-touch handling in general lacks finesse, pinch area often jumps the zoomed content abruptly around the viewport when faced with slimy toddler fingers, far from the graceful degradation of iOS physics. Touch thresholds, velocity and deceleration parameters don’t automatically follow display DPI, making touch interactions like flicking, taps and long-presses pain if the embedded device developer hasn’t realised he needs to tune the parameters himself for each supported display. Writing custom touch gestures and physics is pain as each Qt Quick touch element (Flickable, ListView, PathView, MouseArea, and so on) implementation comes with it’s own subtle differences in the event filtering heuristics. In practice you need to understand the Qt Quick touch event propagation in detail and be prepared to make fixes to your custom touch elements whenever you migrate to newer Qt releases.

Missing primitives

Qt Quick needs more visual primitives. Original Qt Quick 1 provided only a handful of visual primitives like Text element for laying out paragraphs, Rectangle element for creating simple color overlays and borders, and couple different Image elements for rendering bitmap graphics. With these three type of primitives you can compose most applications, but they are not enough if you want to aim higher. Qt Quick 1 was deliberately limited to the few primitives that the old QPainter architecture was able to render in acceptable framerates, but that limitation is no longer valid for Qt Quick 2. Qt demos and examples often pale in comparison to elegant Processing infographics, lively Open Frameworks interactive art projects, ingenious Noodl UI demos, flashy if a bit tacky Kanzi UI 3D interfaces and the smoothness of Berry Forest game built with Zing Studio.

For example efficient line and bezier curve primitives are needed for visualising routes, implementing hand-writing input and other connected graphs. Different kinds of radial and linear gradients are missing that are commonly used for shadows, backgrounds, borders and making emphasis around the interface. Blurs of different caliber, both fast and slower high quality ones are needed for defocusing secondary objects and for creating modern, airy, transparent feel. Masks are needed for forming non-linear shapes, creating fading masks, looking-glass-style widgets and other viewport effects. Qt Quick can draw simple circles, but new API is needed for creating sectors for pie charts and menus, clock and time picker components, progress and busy circles and so on.

A lot of different custom primitives can already be created with shaders, but not everybody is comfortable writing GLSL code, and coming up with a correct, portable and efficient shader implementation is not always an easy task. Canvas API provides many primitives that are missing in Qt Quick, but it is not efficient enough for complex visualisation tasks, and the API is not declarative like the rest of Qt Quick. Qt does include Qt Graphical Effects module, but it feels more like a collection of examples than a productised set of components hardened for real-world scenarios.

Layout limitations

While Qt Quick views and positioners provide a lot flexibility, they fall short in couple areas.

For example Qt lacks proper grid flow layout. Pinterest popularised dynamically stacking grid layout, which frees the grid items from a rigid table structure. Stacking layouts allow increasing the size of important items or reserving different amount of space for different type of content. Qt Quick does have different grid elements, but they all fail in one way or another: GridView enforces constant item size, and Flow and GridLayout elements only allow limited variation, and do the stacking differently to Pinterest.

Qt Quick views like PathView and ListView only create visual delegates for model items that are currently visible on the viewport, which is cool since it allows the views to handle large number of items without sacrificing the loading performance and memory consumption of the app. Unfortunately the dynamic loading is only supported for one model per flickable viewport, which is not enough for modern apps that often mash up information from multiple sources. For example a web store landing page could show three sections: editor’s choices, most recently added content and content recommended for the user based on earlier purchases. We need positioners that are aware of the viewport, but just adding maximumCount property to Repeater to limit the amount of items that get created would help.

Black box typography

Qt Quick offers blackbox-style font APIs with limited ability to affect the layouting paths and no way to animate the text layout changes. This is unfortunate since typography is core part of the overall experience, user interfaces are often primarily made of text. Ability to animate text layout changes in particular would be welcome addition to allow replacing abrupt visual jumps with smooth, graceful transitions.

Positioning text elements alone leaves a lot to be desired. Vertical anchor lines (baseline, mean line) within the text are often as important if not more important than anchor lines around the outer bounding box of the text element. Qt Quick does provide baseline anchors, but oddly only for the the first line of text. In effect implementing a layout created by the designers often requires calculating the exact positions explicitly. Fortunately the new FontMetrics QML element introduced in Qt 5.4 makes such calculations easier, but ideally there would be appropriate anchors also available. Other typography issues include clumsy line height and spacing APIs, issues with the text fitting behavior, and no way to increase touch areas of the links embedded within text element.

Improving text layouting is hard. Text elements are arguably the most complex components rendered on the user interface. Whenever somebody adds a new feature in Qt text layout code half-dozen hard-to-find regressions pop up in text alignment, text truncation, word wrapping, bi-directional layouts, pre-edit handling, Thai spacing rules, and so on. Developers are understandably afraid of making changes in the layouts. Still fear should not dictate development priorities.

Lack of color management

Qt Quick lacks proper color management system. In cross-platform environment the color management is often left for the underlying platform like Windows, but as far as I know in Qt embedded space there are currently no good solutions available. KDE has some color management support, but it requires changes to the graphical applications. Color corrections are often done in GPU, so don’t expect your custom shader code to be automatically color-corrected even if the underlying OS would support color management. Color management system allows calibrating the color representation of the interface between various displays. Without it orange color on one display may look yellowish on another, blue color tilt to green, and so on. Gradients that look even on one device may look flat on other, or produce banding artefacts making the graphics look clumsy and unpolished. Good color production is not only important for visual quality, lack of contrast also hampers the overall legibility of the interface. Also, coloring is often used for indication and highlighting, which falls short if the user fails to detect the difference between the colors.

Tricky models

Making good Qt models is hard. So much so that many Qt models in production are plainly broken, and fail even the simplest CRUD-style tests, just barely serving the limited use cases (like exposing few urls from a SQL database) that the original author envisioned. Some models can only handle couple of thousand data points before the application performance is sacrificed, in some the index handling is swarming with off-by-one errors and for many memory footprint naively grows in proportion with the number of data points. Updates to the model often freeze the main application thread for hundreds of milliseconds due to inefficient way of handling the changes. Developers often load the whole database table in the constructor no matter how much data there is, and reset the whole model or rewrite the whole database to disk even when only few data points are modified. Adding threading support of course introduces another category of things that can go wrong.

There are ways to make good Qt models, but QAbstractListModel provides little support so most Qt beginners fail miserably. While a major source of problems unfortunately there hasn’t been a lot of activity to improve the Qt models architecture.

3 thoughts on “I love Qt Quick, and yet…”

  1. Thanks for the good feedback and solid improvement proposals. I hope we are able to make Qt Quick and the QML JavaScript language better in the coming versions of Qt. It is also good approach to propose new features via bugreports.qt.io and the Qt Project mailing lists. We are also very happy to receive contributions to Qt Quick, if you have time.

    1. I have filed some of the issues to bugreports.qt.io, but definitely could and should file more. In Jolla we should also try to find time to upstream more user interface enablers originally implemented in Sailfish Silica toolkit back to Qt framework. Unfortunately a lot of issues raised in the article are architectural in nature and thus non-trivial to fix, and require months of co-ordinated development, which I guess won’t happen until a company steps up to fund the improvements.

  2. Since you mentioned live tuning of properties, I found that the GammaRay tool allows exactly that and more.

    Even works remotely, not sure any of the web tools can attach from a desktop browser into one running on a device.

Leave a Reply

Your email address will not be published.