Hacker News new | past | comments | ask | show | jobs | submit login
Understanding the Layout Process in Qt Widgets (felipefarinon.com)
62 points by felipefar 34 days ago | hide | past | favorite | 45 comments



QGridLayout is my go-to for applications. I like how it allows a responsive design when resizing. Most of my desktop apps are for simplifying tasks that my coworkers and me are doing, so no one's expecting the most professional look and Qt has gotten the job done.

Have you used Qt Creator? Once I started using this, my app development started flying because I didn't have to edit, run program, edit again. Just drag and drop widgets around, its very nice.


Why do your prefer it over https://wxwidgets.org given the licenses?

Personally, I was keen on Qt right up to the 5.x change over. =3


WX just looks ancient to me, and doesn't have anywhere near as large a community, or as many nice-looking applications built with it. The only big license change in 5.x I'm aware of was moving from LGPL 2 to 3... I don't think that really affects the majority of users unless you're shipping hardware and don't want the anti-tivoization clause.


It uses the native OS themes, so should appear as a standard program.

Ever consider what happens when designers try to redefine 40 years of interface inertia. You get Windows Vista or MacOS 8.... lol =3


What's the concern with Qt's licenses? Afaik, their current license works for me.


Qt 5.6 and later switched from LGPL v2.1 to v3. The main difference is the addition of the anti-tivoization clause that the regular GPLv3 has, wherein you cannot sell hardware that integrated Qt without providing a way for the user to replace your copy of the libraries with their own. Although at that point most people just buy a commercial license, and I think the majority of people that complain about this don't have a legitimate use-case that really affects them as much as they lead on.


Mostly, 5.x broke many dependencies due to how the linking impacted license compliance issues. This meant users would be left to figure out why several features were turned off in the Debian package built.

I prefer wxwidgets, as its lgpl style license allows static-linking on both open or closed projects without submarine-IP-fees... undeniably useful when cross-porting to some platforms.

We may have differing opinions, as our use-cases likely differ. =3


but both Qt and WX is LGPL ?


wxwidgets is a slightly more permissive license than lgpl.

When people must static link on some closed mystery object, than the subtle difference becomes very important.

lgpl works great in the Linux .so design paradigm, but it can cause problems on rare occasion for porting. =3


I'm curious why you chose Qt Widgets for a relatively new application? Is desktop support that much better than QML?

There's a bunch of tradeoffs for everyone who has to make that choice and it's always interesting to know why people choose the one that they do.


Well, I don't want to bash on QML, since I really appreciate the efforts that the team puts in it. But I do think its current state is not the best when compared to Qt Widgets, and lament that there's a split between the two toolkits inside the framework. The problems I had with QML are:

1) The controls that Qt Quick 2 provides are oriented toward touch interfaces, and some are not even feature-complete. For example, QML's Flickable on desktop can be scrolled by clicking and moving the mouse, a behavior that is clearly an artifact from the touch implementation. QML's TextEdit doesn't support much that QTextEdit does, which was particularly important for implementing an app that offers advanced text editing. Ironically, even though Qt Quick is touch-centric, Qt has lots of bugs on mobile platforms, and has a history of presenting regressions on those platforms.

2) Communication between QML and C++ is finicky. You have to use macros and Qt-specific constructs (Q_PROPERTY, signals, slots) to bridge both worlds. Qt Widgets doesn't need bridging in the first place, since it's C++ all the way down.

3) Control customization is a pain. In Qt Widgets, we can create a class that inherits from a standard widget, and then we can customize it however we want while inhering the behavior from the base control. In QML, you have to resort to javascript for that, which has different tooling and ecosystem than C++. Besides, C++ programmers find javascript dynamic typing more error-prone than static typing.

4) The latency of interfaces built with QML is higher than the ones built with Widgets. QML's rendering engine is lagging behind in the input latency mitigation front when compared to browsers, although they've been making efforts in this area.

I don't think those problems are unsolvable, and historically Qt has evolved a lot, so I hope they eventually tackle these issues seriously.


Thanks for the detailed response! I'm definitely feeling the majority of these paint points.

> 2) Communication between QML and C++ is finicky. You have to use macros and Qt-specific constructs (Q_PROPERTY, signals, slots) to bridge both worlds. Qt Widgets doesn't need bridging in the first place, since it's C++ all the way down.

This hurts so bad. I'm actually implementing in Rust so I've got double the pain and any Rust type is either a QVariant or *mut pointer but integrating with Serde to easily (de)serialize JS objects has mitigated some of the pain points.

> 4) The latency of interfaces built with QML is higher than the ones built with Widgets. QML's rendering engine is lagging behind in the input latency mitigation front when compared to browsers, although they've been making efforts in this area.

This one is surprising. I've had more problems with Widgets, especially when doing a lot of animations (even just scrolling big text views) on a 4K display on MacOS, but maybe I'm thinking graphics and not input lag. The software rasterizer/GPU pipeline seems to get overloaded on Mac (Great article on the rendering pipeline btw!)

The big thing that sold me on QML over Widgets - other than the latter being the redheaded step child by this point - was implementing hot reloading. Having the entire UI completely refresh when changing the QML is definitely a nice coming from browser frontend, especially given Rust compile times.


> I've had more problems with Widgets, especially when doing a lot of animations (even just scrolling big text views) on a 4K display on MacOS, but maybe I'm thinking graphics and not input lag.

There's two things to consider when comparing rendering performance: throughput and latency. Throughput, or how much FPS the engine can sustain, is much better in QML since it's leveraging the GPU, but latency it's very platform-dependent. Mac is actually the one where QML does best in terms of latency (and by that I believe it approaches the latency of Qt Widgets), since it's synchronizing with the VBlank signal provided by CVDisplayLink. On Windows and Android the situation is worse.


Sidenote: Have you seen the new TextEdit improvements in Qt 6.7? I'm curious if that bridges the gap that you had when you started working on your app. My app is also text editing heavy so I'm hoping it's a big improvement.


I saw them, they are a very small step in what I believe is the right direction, since you can use a custom textDocument. Anyway what I think would be useful is to jailbreak the QML API. Make the QML C++ API publicly available. Let us derive from the controls, manipulate and customize them with C++, as the Qt team devs themselves do.


I've created my own block editor from scratch using Qt C++ and QML, which is way faster than a regular QML TextArea[1]. Which is funny since it's just a ListView with Blocks (that contain TextAreas).

[1] https://www.get-notes.com/


> The big thing that sold me on QML over Widgets - other than the latter being the redheaded step child by this point - was implementing hot reloading. Having the entire UI completely refresh when changing the QML is definitely a nice coming from browser frontend, especially given Rust compile times.

Interesting, are there any public examples on how to implement this? All tools I've seen to do this seemed to be commercial offerings, though maybe implementing it in an existing application is easier than I think.

actually now that I'm looking again I found https://github.com/patrickelectric/qhot, which also looks promising


It’s very easy to implement a naive version. It only took me a few hours with the help of GPT/Claude and most of that was figuring out how to save and restore all window positions.

All it is is Rust’s notify listening for any changes in my QML directory and calling a C++ function on QQmlEngine: https://pastebin.com/08QKu84H

It'll require a bit more work once I'm loading multiple root QML files but for now it works great. It doesn't explicitly restore any state, however, but I store most of my UI state in Settings and a custom component that syncs arbitrary JSON values to Sqlite so the previous state is automatically restored when the QML is reloaded.


Ah, I somehow assumed more magic would be needed, but indeed it's really as simple as deleting the top-level widget and recreating it. And then repopulating the properties is what gives it the illusion of being dynamically live-patched.

I'll take a shot at implementing this in some of my code as well. Thanks!


> For example, QML's Flickable on desktop can be scrolled by clicking and moving the mouse, a behavior that is clearly an artifact from the touch implementation.

This should be fixed in Qt 6.9: https://bugreports.qt.io/browse/QTBUG-97111

> Ironically, even though Qt Quick is touch-centric, Qt has lots of bugs on mobile platforms, and has a history of presenting regressions on those platforms.

That's interesting. I'm soon planning on porting my app to mobile using QML so I'm curious how that would go.

> QML's TextEdit doesn't support much that QTextEdit does, which was particularly important for implementing an app that offers advanced text editing. Ironically, even though Qt Quick is touch-centric

I think the latest changes that expose textDocument and others are very good improvements[1]. Even without these, I managed to write my own advanced block editor using QML[2]. It took around 5 months but it was well worth it and quite straightforward to implement.

> The latency of interfaces built with QML is higher than the ones built with Widgets. QML's rendering engine is lagging behind in the input latency mitigation front when compared to browsers, although they've been making efforts in this area.

When you speak on input latency, what do you mean? For text? I really don't see much of a difference (at least here on my Mac). I saw you wrote that on Windows and Android it's worse. On Windows I didn't see an issue nor did someone reported about it.

[1] https://www.qt.io/blog/text-editing-improvements-in-qt-quick

[2] https://www.get-notes.com/


I recommend checking out Qt design studio. Once you get the flow on there, it creates a nice clean separation between the UI and backend.

While it may seem like Qt Quick is designed for touch primarily, it is not actually the case. Modern UI/UX design is a bit more abstract, and requires a bit more skill to get working.

My recommendation is to be patient, and work with Qt Quick it will pay off in the end (e.g porting the app to Android, etc). Focus on the UI/UX completely separately from the backend. And once that is established, the models can be developed in C++.


I can't speak for the author, but many systems programmers look at declarative/markup-based UI as a kind of black magic that you can't trust and that will get in your way sooner or later by not leaving a sane way for you to address some project requirement.

We/they are often way more comfortable working with the kind of programmatic widget and graphics library that we/they might write, and whose behavior we can debug and trace with our usual tools, then somebody else's weird new declarative/markup syntax that obscures what's actually going on behind the scenes and frustrates our tooling and workflow.

And this instinct traces back many decades, for as long as visual RAD tools and declarative UI syntaxes first started being introduced by big vendors.


> I can't speak for the author, but many systems programmers look at declarative/markup-based UI as a kind of black magic that you can't trust and that will get in your way sooner or later by not leaving a sane way for you to address some project requirement.

This exact scenario has played out for many trying to adopt SwiftUI. For even moderately complex projects it’s common to get 90% of the way there fairly easily, only for that last 10% to be a struggle/slog as a result of its inflexibility. AppKit/UIKit may not be trendy or sexy and might take longer to get new projects spun up with, but it’s much more rare to hit that brick wall with them; you’ll probably be able to accomplish what you need with little or no pain.

I’ve seen shades of this in Jetpack Compose too, which makes me think that these sorts of problems are just inherent to the type of UI framework.


I'm curious to hear more about those problems. Do you have any articles covering them in more depth?


I've seen a few blogposts on the subject over the years but wouldn't be able to reference any of them on short notice.

In short though, frameworks like SwiftUI tend to be designed around a very narrow set of use cases and if yours deviates from those in any way you're in for a bad time, and depending on how great the deviation is will likely land you with falling back to older imperative frameworks for their more customizable/hackable widgets in places (if that's an option) or dropping the declarative framework altogether.


Amen. I've coding in Qt since v1.x and have never felt the need to switch to QML.


Widgets imitate one of the native UI toolkits (Win32 CommonControls, macOS AppKit) and can be embedded within those, and native widgets (HWNDs/NSViews) can be embedded within QWidgets.

QML is a strange GPU canvas world that looks mostly alien and behaves just so slightly more different that it is immediately noticeable and annoying.


Desktop and tablet/phone applications need very different UIs. Anyone who tries to force the same UI on both is wrong and needs to be forced back to human-machine-interaction school (odds are they never went in the first place)


Rust bridge with C++ is a solved problem; since they have the same calling semantics you can easily bind rust callbacks to your c++.

JavaScript-Rust bridging (or any managed language) is slower and more effort to explicitly design.

My $0.02 would be: with widgets you can implement a lot of complex backend logic in rust, using a package manager that works (ie. cargo) to get significant productivity gains from the rust ecosystem for implementing the logic of your application. Specifically for example, threaded processes, network interactions and file parsers / exporters which get you “for free” functionality for eg. Loading .vox or .fbx files in an app, then passing them to c++ for processing / editing / rendering in the ui.

With QML you’d have to do that by hand. What a meaningless chore.

Also with QML, the runtime is not node compatible, so forget using existing packages in that ecosystem to help.

(There are obviously downsides too, like rust for mobile, but for desktop applications rust static builds are trivial to bundle in the c++ build process using cmake).


I'm also interested. I've been a UI developer for a long time but I've only ever built websites (with a brief stint doing iOS work), so I have little-to-no knowledge about native desktop UI solutions. I'm aware of QT and imgui, but beyond that I'm not familiar with the landscape.


QML wasn't (at least in the Qt5 days) a good fit for traditional desktop style applications. It was nice for more multimedia touch screen stuff, but HTML5 in an embedded browser like CEF or Electron was catching up fast and with much better third party library support.


I’d love to see an article on Qt text layout processing.


That's actually a great idea for a second follow up article. I've worked a lot with rich text and custom text objects, but would also like to explore itemization and the lower level layers.

What would you like to know more about it?


I'm curious how they are doing it from paragraph segmentation to text runs... it's an incredibly complicate algorithm if you are accounting for all scripts known.

I've looked at the LibreOffice text layout algorithm, so I'm curious how Qt handle text layout!


Managing widget size and layout in complex UIs is definitely one of the more challenging aspects of programming with Qt. But you usually get what you want with a bit of trial and error.


I am running up against it now. While QT works on the major OSes, it somehow manages to not quite fit with the design of the OS - which drives me crazy. If I wanted it to sort of behave like a Windows app, I'd write Windows apps. Sadly, it's the best option for Python.


I think Qt looks and feels pretty native on Windows. It doesn't look quite as native on Mac, but it's not far off.


Qt has a chronic problem with High DPI displays, especially when mixed with a lower DPI display in a multiple monitor situation. You will never get it 100% right and when you start shipping it to users that percentage will fall quickly.


I haven't had a high DPI issue with QT in quite a while. Early in QT 5, high DPI presented many problems, but they have been slowly settled over time, including by using sane defaults.

Source: I develop a QT widget app and develop on a workstation with mixed high and low DPI monitors.


Qt 6 is supposed to handle high DPI better. Does that not apply to multiple monitors? I have not noticed any issues.


This is my stock response when anyone complains about CSS; consider the alternatives.


I found Qt way easier around 2010, maybe the new flexbox stuff is good though?


With CSS you typically need a lot of trial and error, and then there’s different browser implementations and versions on top of that.


I prefer Qt layout to CSS any day.


Only one picture?




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: