What even are Breeze, QtQuick, QtWidget, Union..?
49 points by Aks
49 points by Aks
I feel like this post is a pretty good example of the reason why there are so few cross-platform native apps released.
People in the comments here and on HN love to rip on Electron apps and web devs and blame JS as a language (and JS/web devs) for every janky web app they encounter, but look what the alternatives are. Instead of React/HTML/CSS/JS, you have to learn some super specific semi-platform-dependent combination of frameworks which is all chained together by C++ classes with names like QStyleOptionTabWidgetFrame.
import { DatePicker } from '@mui/x-date-pickers/DatePicker' becomes a 21 story point odyssey that ends in a "wontfix" pull request on some invite-only Gitlab server sitting behind a broken Anubis banner.
I dunno.. last time I used Qt was 20 years ago but oh man the experience was smooth. Qt Creator is top class for C++ development and QtWidgets is as full featured as it gets. Never used QtQuick, but it only adds smoothness. If you can handle Electron you can handle QtQuick.
I can’t question your experience, but I’ll offer my own.
I have tried writing Qt in Python, which was a surprisingly messy affair between many versions all incompatible with each other, and functionality that was straight up missing in various ones. (I was a noob, but isn’t the price of entry the topic here?). It also made very strong opinions about how I need to structure my software, which was intended to be pretty basic but then I had to care about async and event loops and other weird things- it just brought in a lot.
Then I tried again when I was writing Go, and that was a lesson in pain at the time.
I tried again later in Rust; that was also extremely painful. Moreso than python and Go.
Then I finally tried in C++, and that was an amazing experience.
I guess the concepts map cleaner onto a C++ codebase.
I guess the concepts map cleaner onto a C++ codebase.
That wasn't my experience trying Qt. The concepts map very cleanly to Java and Qt went to a huge amount of effort to make C++ behave like AoT-compiled Java.
Using OpenStep / Cocoa from Objective-C felt like the language and frameworks had been designed together and reinforced each others' strengths. Using Qt felt like the authors really wished they were using a different language and fought the one that they'd chosen every step of the way.
Probably you start from a modern C++ perspective, but Qt has been around since even before the C++98 standard and until C++11 (around the Qt 4 lifecycle) it adopted a perfectly suitable C++ programming style for the time. Then it’s honestly difficult to retrofit such a huge codebase to a modern style, even though they made some progress.
That's fair, I never tried Java, the concepts probably apply much stronger there, since probably what made C++ work so well is that the concepts are mapping to Object Oriented stuff.
Python was just a bad one, the fragmented ecosystem was probably the most annoying bit, and the fact that it wants to hijack the event loop.
I can't imagine Java being better though, Qt prefers "signals"/"slots" and Java prefers listeners and afaik there's no first-party Qt binding (as opposed to C++). I feel like Qt is coming "batteries included", and then a lot of better languages already have the batteries, so it conflicts.
Yes, Qt is definitely C++-first. I’ve never used it in Python or elsewhere. It’s sad that there are no compelling alternatives for other languages.
Same, I would take building a UI with Qt over web tech any day. I just wish Qt was more usable outside of C++ and Python.
There are modern alternatives emerging that even support development with Qt Creator/Designer via custom tooling:
C
Go
Zig
There are other languages with varying support/maintenance but none that I am aware of that offer the same level of tooling/support for the Qt native ecosystem. In theory, the straightforward and thin C ABI layer these listed projects share as a common backend could serve as a platform for other compatible languages but someone would need to be willing to execute and maintain the respective language bridges.
I've used both, although I'm not quite "as fluent" with QtQuick (which I've used less, and mostly for hobby projects) as I am with QtWidgets (which I've used more -- since it's older -- and in a professional setting, too). I think you're massively overestimating both the difficulty of getting "native" looks with QtWidgets (I'll get back to the scare quotes in a moment) and how much easier things are with things like Electron.
If you use QtWidgets alone, you don't end up touching QStyleOptionTabWidgetFrame. Qt wraps around a lot of native functionality. There are some quirks, and sometimes the Qt platform lags behind recent changes in native appearance, and on some platforms (Linux, in particular) there's really no such thing as "native", hence the scare quotes -- but even with all of these you still get something that's orders of magnitude closer to native than anything web-based.
The very entangled diagram you see in this blogpost is KDE's own doing and specific to their stack to some degree, because they're explicitly after two things:
Now #2 is exactly as hard a problem with QtQuick as it is with Electron and for all the hate KDE gets for bloat in their theme engine (Breeze is a theme, sure, and that happens via a theme engine which literally has a goddamn D-Bus interface) I think they come closest to solving it than any other platform.
That tangled mess isn't there because somehow native toolkits are weird, it's there because KDE is trying to get both the native widget set and their QtQuick applications to look good together. KDE could just go the Electron development way -- make a cool-looking theme that looks nothing like everything else, call it the default, and get on with it -- and 90% of what you see in Aks' post goes away.
Now for the nasty part: I don't think we should let low-effort "real programmers don't use JavaScript, I like to grit my teeth on segfaults like real men do" orange site bullshit discard all the critical outlook on "non-native" (insofar as there's such a thing as native on FOSS platforms) toolkits.
Even with all the effort that went into keeping Kirigami's looks in sync with everything else, I can still immediately spot an application or component that uses QtQuick instead of QtWidgets, even though both have the same Breeze theme. The one that takes a long time to start up the first time, has weird layout quirks, and misses some basic functionality (sane color picking, for example) is the QtQuick one. That's how I spot React/Electron apps, too.
A lot of QtQuick (or Electron/Tauri/whatever-wrapped React) applications don't really try to get "native" layouts -- i.e. they're doing things closer to Spotify's very web-like UI than to, say, Dolphin's, or Windows Explorer's. That works very well. But in my experience, as soon as you try to coax them into native-like layouts, things that start with import { DatePicker } from '@mui/x-date-pickers/DatePicker' also commonly devolve into 21 story-point sagas about dropped frames, the date picker being scattered all over the screen or compressed to 2px heights and so on.
I suspect most of the hate comes from a different source. If you already know C++, you can get started with Qt Widgets right away, and you get all the benefits of a C++ environment that you know -- excellent IDE integration, static analysis tools and so on. Whereas if you try to use React (or QtQuick, too, really), none of your C++ knowledge helps, and the development experience kind of sucks compared to what you were used to. Most of that results in rage that's eventually distiled into online flamewards, but some of it just causes legit software quality issues.
It's not a coincidence that KDE is working the hardest to fix this, because they're shipping applications that use both, so it makes these problems all the more obvious. They're all within KDE, so nobody can point fingers and say look WE'RE fine, it's the unwashed masses of Electron developers who are ruining this. That's also why they're the ones getting flak for the tangled mess: they're trying to reconcile two very different types of frameworks instead of saying oh sure no two apps look alike but HAVE YOU SEEN HOW GOOD THE BRANDING IS NOW??? -- and that's bound to add to the complexity, not take away from it.
You very very rarely have to even think of something like QStyleOptionTabWidgetFrame, only when creating super custom things, or when creating a complete 100% custom QStyle (even Breeze relies on some default values).
QtQuick makes this easier (IMO) because of QML. In there you use templates of main components if you want to create something new, or inherit the default component and modify it.
This can be considered as a "sister post" for my other one here: https://lobste.rs/s/gzqqun/breeze_qtwidgets_style_changes_help_us
For a deeper understanding of QtWidget vs. QtQuick, a colleague of mine recently published a series of blog posts about how to migrate an app from QtWidget to QtQuick. This might of interest for people looking into how to unify styles and behaviours in their Qt app: https://www.qt.io/blog/qtwidgets-to-qtquick-application-journey-part1