[Development] Scalable UIs in QtQuick (take 2)

Rutledge Shawn Shawn.Rutledge at theqtcompany.com
Fri Feb 19 13:45:57 CET 2016


> On 18 Feb 2016, at 11:50, Hausmann Simon <Simon.Hausmann at theqtcompany.com> wrote:
> 
> Hi,
> 
> A little while ago Lars and I proposed to introduce physical units in the QML language for use in QtQuick. The idea was to make it easier to write user interfaces that adapt to different display resolutions by "pinning" your UI to physical dimensions. For example you could say
> 
>    Image {
>        source: "mypprofilephoto.png"
>        width: 5cm
>        height: 5cm
>    }
> 
> and the image size in physical pixels would scale accordingly to always produce a 5cmx5cm profile image on the screen. The proposed units included "px", which was really an alias for nothing.
> 
> We've had some very good discussions around this at last year's contributor summit as well as in smaller face-to-face discussions. The main feedback I recall was that this would seem like a nice feature on paper but in practice people create their resolution independent interfaces using the current "pixels" and a scale factor that they introduce in a qml file or as a context property. That's another way of saying that perhaps the feature wouldn't really find any use, which is fair :). Instead the desire was expressed that making it _easier_ to scale "logical" pixels in the application would perhaps be better.
> 
> So today during a discussion another idea came up:
> 
> (1) In order to make it really easy to scale "logical" pixels without having to introduce your own context property or factor in a .qml file that you multiply everywhere, we could turn the regular "pixels" in QtQuick into truly logical pixels that scale with an application wide (or window wide) factor. So Image { width: 100 ... } will scale automatically from 100 logical pixels to maybe 200 physical pixels on a x2 display. This assumes the availability of API to change this mapping.
> 
> (2) In the events where you still _want_ to use physical pixels, you could use "px" units.
> 
> So at first nothing would change for app developers at all because we map logical pixels to physical pixels. But
> if you'd like to, you could opt into changing this mapping and having a relatively easy fallback to physical pixels using for example the "px" unit. We might as well offer the other physical units anyway, that probably causes little to no harm.
> 
> What do you think?

I thought support for units was on the way a long time ago.  How soon can it be finished?  It would be great to have extensible unit support, and not all of them need to be direct physical units either.  I think we need some unit which is related to the user’s choice of default font size somehow (e.g. Android provides global settings for this, and so do some desktop environments).  CSS specifies it in various ways:  https://www.w3.org/TR/css3-values/#font-relative-lengths

It took me a while to find again the reference to measuring in arc-minutes, but that is here:

http://article.gmane.org/gmane.comp.lib.qt.devel/6863

But it’s easier to empirically adjust readability of text than to measure the user's ability to perceive a single dot; eye charts are made with text for a reason I think.  And what’s really more important than designers being able to specify what they want, is for the end user to have total control.  It’s very important to have a zoom control of some sort - preferably both a global one (like the Android font size setting - do we even respect that yet? or like Qt’s various confusing env variables), and a more-local one for correcting design mistakes (just like ctrl+ / ctrl- or ctrl-mousewheel in your browser, same thing in Creator’s editor, in our help system, etc).  For the global setting, the easiest thing for the user is to specify a default font size - that’s a subjective choice based on preference as well as visual acuity and distance.  So maybe the best way to design the visual aspect of most applications is to use font-based units (like the em space) for physical sizes, but for touch UIs, to also use physical measurements as a minimum.  e.g. width: Math.max(7mm, 3em) - will it be possible, or can we have nicer syntax?  For example a button must be able to fit its text (unless it’s so long that the designer plans for it to be elided), but the button must also be at least 7mm in both dimensions to be touchable.  The user should choose the text size, while the designer should choose the minimum widget size, and otherwise tie physical size to text size.  If the user chooses too large a text size, then less stuff fits on the screen… that’s the usual tradeoff.  And Qt has always had decent layout management, to make use of increasing or diminishing space effectively.

Qt’s lack of non-integral devicePixelRatio has been problematic.  Users need fine-grained control without tweaking individual applications and style sheets and preferences, all in app-specific incompatible ways.  Fortunately non-integral scaling is supposed to be getting done eventually (but it should have been several years ago).  Unfortunately it’s done by means of too many confusing env variables which seem to change with every Qt version.

In my ideal graphics toolkit, pixels don’t exist, the default unit was always millimeters since day zero, and sizes are guaranteed accurate on every device as long as zoom = 1.  If you want to scale differently, you have to be explicit about it in your app, or the user can override it at runtime into an explicit “uncalibrated” mode.  It’s like the Postscript doctrine, except that they chose points instead of millimeters.  And it’s highly compatible with the fact that the OpenGL coordinate system is normalized by default, and you must determine the total transformation matrix from model to normalized to screen coordinates yourself.  Much nonsense has been perpetuated because designers refuse to forget about the pixels and move into the post-pixel world of high-resolution displays.  In the limit, pixels are like molecules in paper, or grains in film emulsion, with varying size depending on the substance; but we require an independent unit of precision, rather than molecular precision, to measure pieces of paper and text and graphics on the page.  Even on low-resolution displays, the reason for antialiasing is to render graphics the same way a camera would see them.  You will perceive the image smoothly enough without worrying about the color and alignment of every grain on the film.

But although the majority apparently still disagrees with that (for how much longer, I wonder?), and even though entrenched legacy apps are making a real transition impossible, we at least need a way of achieving it by choice in new apps.  And a selection of various proper units in QML would be a great feature in both the ideal world and the real one, as long as we strive to ensure that physical units are accurate by default, and can be calibrated accurately on hardware that doesn’t tell the truth about its own scaling.

I also wish the ctrl+ / ctrl- / ctrl-mousewheel way of tweaking the zoom factor in individual widgets was more universal, because designers and developers will always choose bad sizes sometimes, no matter what tools are available to them.



More information about the Development mailing list