back

by LorenDB·2y ago·view on hn ↗
QML is not "magic". It's a separate language that integrates with C++ and makes UI design easier, sort of like how webpages use HTML/CSS for the graphics and JS for the logic.
1 comments
When it is unclear how my app compiles this separate language together with C++ it is magic. When I attempt to write an application and someone says “use this other language and don’t worry about the implementation details” that appears as magical to the implementer.

Magic can be de-obfuscated with documentation but if I can accomplish the same thing in C++ with nearly the same amount of code, then the magic isn’t for me and C++ is a lot more clear and reduces cognitive overhead.

> but if I can accomplish the same thing in C++ with nearly the same amount of code

That's not the case when it comes to QML/QtQuick though. It sounds like you were writing a desktop application, So C++/QWidgets were probably a better choice for your use case. But for embedded/mobile use cases, where reactive, smooth animated user interfaces are the norm, QML is on an entirely different league.

Also, with QML I didn't have to worry about the ugly combination of junior engineers and C++ footguns.

I've been working on a team replacing a widgets UI with QML, everyone on the team loves QML and finds it way easier/faster to work in (and the design/management love all the smooth animations etc.)

and the guy who sucks at C++ breaks things less

Yeah that's more or less how it was for us too. Do make sure QML has all that you need. On Desktop (this was back in 2018, so ymmv), things like table view, undo redo stack, other integration features were missing.

Our journey was like: "Wow.. this is so nice and easy.".. 70% later.. "Should have researched this better. Now we have to mix QWidgets with QML code to get what we want".

I’m working in mobile too but have no use for smooth animations (which is of very little value) so QML isn’t really valuable. I also do not like the idea of embedding a browser stack and forced to write JS just for that purpose. The point is to keep my code in C++ and not hop around to x different files to make sense of my application.
QML is NOT a browser stack though. QML is just a way for you to script QObjects. QtQuick - on the other hand - is a very performant GPU accelerated scenegraph that can be scripted using QML.

> The point is to keep my code in C++ and not hop around to x different files to make sense of my application.

Another point of view that differs from this is - QML lets you easily separate UI logic from business logic, to better make sense of your application. Especially when it comes to "responsive applications". For eg. All the UI related parts of your application stay in QML files in folders like desktop/ android/ common/ etc... All the "backend logic" stays in C++, ready to be used by all these UI elements.

It is not about being forced to write JS. Nothing stopping you from writing very declarative looking C++ either (fun article: https://woboq.com/blog/property-bindings-in-cpp.html ). It is just about using a better tool for the job. State machines. Reactive properties. Declarative UI description. All of these make you need a lot less code than writing everything in imperative c++.

It’s not a browser stack but includes an HTML painter and V8 engine in your project? This sounds pretty close to a browser stack to me. If this isn’t true then this is one of the confusing aspects. In including pieces of a browser stack or whatever is going on doesn’t really help it make it look not like one. It seems like the ideas are obfuscated just to call it something else.
HTML painter? you mean how QLabel supports rich text via. HTML tags?

Not sure what you are getting at with the "ideas are obfuscated to call it something else". You'd have a widget tree/graph even with QWidgets/QObjects. Would you call any QWidget program that uses QJsEngine "a browser stack"?. QML is just a declarative programming language, that lets you script QObject properties/react to signals/property changes.

  NumberInput { id: width }
  NumberInput { id: height }

  Label {
    text: "Area value is: " + width.value * height.value // automatically gets updated
  }
All expressions in the above snippet of code are basically Javascript expressions. To accomplish the same in pure C++, you'd need to implement some kind of observer pattern/manually connect signals and slots across objects to allow for updates of dependent values (Label's text).

QtQuick is a scenegraph that uses QML to render a GPU accelerated UI. Which is what is needed on embedded/mobile UIs to get smooth high performant animated GUIs. That'd be too ineffecient and cumbersome to accomplish with QWidget/C++.

In QWidget if you use it then it’s compiled into the application. If you use QML it’s always there as far as I understand. Please review this post which seems to indicate that JS and HTML components are added to a project when QML is used.[0] It may not be a full engine but as I’ve previously stated I’m not interested in writing things in multiple languages. I want as few extra languages as possible. To tell me it’s not a browser stack then go on about how to use QML you can declare pages in HTML and JS that are then compiled into the binary that passes data between C++ and JS is entirely ignorant of my initial goals. If I wanted to use browser technology and JS I would build my app for a browser.

> To accomplish the same in pure C++, you'd need to implement some kind of observer pattern/manually connect signals and slots across objects to allow for updates of dependent values (Label's text).

I do not find that extra work because it’s represented in the class itself and the observer pattern maintains my preferences.

Perhaps these technologies are useful for those who want to quickly write a mobile app with slick animations. Indeed it is a easy way for Qt to gain audience for those types of apps especially for people who aren’t able to learn C++. For my intentions I am looking for less overhead overall to keep files as pure C++ as possible to ensure that a class I’m writing represents the full scope of it’s functionality and domain.

[0] https://news.ycombinator.com/item?id=38395603

I think it doesn't include a V8 engine anymore. Qt has its own JS implementation as far as I know. And it doesn't have a full html painter (If you don't use QtWebEngine)
Initially QmlEngine used to use v8 for the javascript interpreter around Qt 5.0. They quickly migrated away from that to their own interpreter for various reasons: https://forum.qt.io/topic/32701/qt-v8/4
C++ is not the language for GUIs on mobile. There’s not a single mature, widely adopted framework that supports C++ for laying out widgets/views/GUI elements.
Where it is that you see "magic"? QML is a markup language (just like HTML is for web) which can have inline code in it (JavaScript). These QML files are quite literally embedded into the binary, loaded in-memory at runtime, and processed by a rendering and execution engine. Quite similar to how a web browser would render HTML and execute JS code. In fact, the latter in QML originally was done by V8 itself!

The extra feature of the QML engine wrt. a web browser is to provide callbacks and hooks, doing what I guess we could call FFI, allowing for events and function calls to travel between C++ and JS. Complex, but not much sort of magic in there.

As far as I understand, we would draw a parallel between QML and what Tauri does. It just embeds a whole interpreter into your program, in order to be able to draw the markup and run the scripting.

For a beginner to Qt (not necessarily programming. not even C++. Just Qt.), most of this tends to be magic though.

The build system automatically embeds all the QML files into the program binary. The QObject system transparently adds reflection to C++, using the build system. The QmlEngine that keeps track of properties that are in use and automatically updating the dependent values, and the headaches that come with broken bindings.

Not saying it is a big deal to learn or anything, but a lot of this stuff is not what "traditional C++ devs" are used to. I had to teach some new devs "Intro to Qt for C++ progammers", so i got to see this from their perspective.

But that's a knowledge issue. Which is fine, if I can say one thing for sure is that none of us was born knowing anything at all :-)

C++ programmers would probably be used to lower level kind of technologies, but when talking about this I think it just helps to think about what would you do if you wanted to embed an HTML and JS file into your program and wanted it to work like QML works.

For an experienced C++ dev, a list of stuff will naturally start flowing through their mind:

* A mechanism to inject the files into the binary upon compilation.

* How to interpret the HTML and paint on the screen? We'll need an HTML rendering engine and a surface painter.

* About JS, how to run it? Well, maybe time to include V8 into the program. It will take care of running JS code.

* Now to make calls between both languages. Probably V8 already provides callbacks because it implements FFI already for you.

* And other stuff you mentioned, like a property manager that remembers what has been registered and creates change observers in order to trigger events for C++ to know.

Thing is, Qt already gives you all of this done, otherwise their proposal of QML wouldn't have gone too far...

These series of articles touch on the topic and can enlighten a bit about some details:

* https://www.kdab.com/qml-engine-internals-part-1-qml-file-lo...

* https://www.kdab.com/qml-engine-internals-part-2-bindings/

* https://www.kdab.com/qml-engine-internals-part-3-binding-typ...

* https://www.kdab.com/qml-engine-internals-part-4-custom-pars...

> But that's a knowledge issue. Which is fine, if I can say one thing for sure is that none of us was born knowing anything at all :-)

It is just that for them, "non c++" tools ended up doing a lot of this magic work. Plus the idea of "embedding another language or two into a language where i already made UI without any fuss" tended to keep some of the more experienced C++ devs away from QML in my experience. Giving them tasks like animating the UI, writing custom styles etc.. that's where QML converted more C++ devs in my experience.

Those kdab blogposts were indeed very helpful for us back then.

The reality behind 'Magic' is always a 'Knowledge' issue ;-)
No offense to Qt but if I wanted any of that I’d write my app for a browser. There is very little benefit to write something that works just like a browser with extra overhead when I’m trying to write in C++.

That’s usually what people mean by magic, extra complexity that is not apparently beneficial even when partially understood.

So you always look at the generated Assembly to understand the magic behind producing a native executable, and the magic behind unrolling for loops into sequences of AVX512 instructions, or the magic behind inlining a virtual method dispactch,...?