Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Ask HN: Good architecture for C++ / QML projects?
23 points by laurent123456 on Jan 26, 2017 | hide | past | favorite | 14 comments
I've been reading about this for some time but can't find any good technique. Basically I'm wondering how do people architecture C++ / QML projects and in particular the communication between the C++ and QML side.

In general I can get things working but after a while it becomes a mess of signals and slots, some signals being queued other immediate, which makes it very difficult to reason about. Basically it's not clean like a React/Redux architecture or MVC on the server-side can be.

I did stumble across "quickflux" but that seems a bit of a complicated hack, while I'd rather go for something simpler and more native to C++/QML.

Any suggestion?



Do you actually need QML? What's wrong with "native" widgets?

I ask because I use Qt and c++ professionally, and have no use of QML. I could elaborate, but I'm more interested in why exactly you'd go for QML first.


Yeah, second hand story (as in, personal friends are working with Qt/C++/QML, i've fortunately only used Qt/C++) is that QML mostly gets in the way. It's limited and buggy. Just do everything natively, Qt is truly cross platform and you won't have trouble.


In fact I'd rather use native QWidgets as I find it much easier to work with, however as I understand Qt is now increasingly giving priority to QML so I'm trying to use it for this new project.

Also this is a mobile app and it seems Qt Quick is designed for this. I'm curious actually are the apps that you develop meant for mobile devices as well? And if so, how does the QWidgets work on them?


No, I don't develop for mobile, so I cannot answer there. Exclusively desktop.

I know Qt5 is pushing towards QML, but QWidgets aren't going away. In fact, I would consider it to be a big mistake to use QML on desktop. It's much slower and doesn't really save the developer anything: pushing state to the JS layer doesn't you any good if you need to keep it sync with the lower layer as well. It's an extra indirection. It also looks completely out of place in all platforms.

QML might be partially useful for drawing on GL surfaces, but again the performance hit will be a huge setback. We use different widget kits for drawing on GL. Since QML and QWidgets are different anyway, there's no reason to stick to it.

Also, QML widgets are improving, but they're all still qualitatively inferior from an user/usage perspective.


I wonder why people want to use/abuse signals and slots in QML, when it's perfectly possible to just use good old plain functions in a language binding, like it is done here (for ECL/Common Lisp):

https://gitlab.com/eql/EQL5/blob/master/examples/M-modules/q...


QML evolved from binding Qt C++ objects into QtScript (JavaScript). If your QObject has Q_PROPERTY, signals, slots etc. you can access it from QML too.

Did you see https://doc.qt.io/qt-5/qtquick-modelviewsdata-cppmodels.html already?

Shamless plug: You can also ping us at info@woboq.com and we might be able to help with architecture/development of Qt applications.


Btw, do you get enough leads from your website?


On my last project we started an effort to redo our QWidget implemented UI with QML. The QML version was really slow, we actually ended up buying a commercial license to get access to a QML compiler just to speed things up. And that was for desktop, I'd expect it to be even worse for mobile. Integrating the QML components with the QWidget components was especially buggy. For a 100% QML project this would be less of a problem.

Interfacing C++ to QML is clearly not a priority in the design of the whole system. You can do slots/signals or you can register C++ objects into the QML namespace. Something along the lines of this tutorial: http://doc.qt.io/qt-5/qtqml-tutorials-extending-qml-example....

Overall, I find the whole QML environment to be disappointing and I don't plan to use it again until it becomes more mature.


I've ran a few QML tests on Android (reading/writing to/from an SQLite DB, displaying the results in a list, synching with a web API) and it seems reasonably fast. Did you identify something in particular that was making the app slow? Or was it just that the app was particularly complex?


To my recollection, the worst performer was parsing all of the QML at startup. This did not impact us at first, but as we grew the QML portion it went from a noticeable delay at startup to an unacceptable delay. It was something on the order of 10-30 seconds (on rather high-powered workstations to boot) to parse all of the QML files for what amounted to less than a dozen UI screens.


I personally liked the idea of using QML, but the C++/QML interface made using it difficult. In the end I end up making another toolkit which consumed QML-like files and executed them using the mruby VM which has a much simpler C interface.


So this is where I'd start[0].

Their site has amazing documentation. I personally found Qt even in the KDE2 days miles better than React/Redux and non-Smalltalk MVC's. Since then it's only gotten better. Check out the examples here[1], the diving in section here[2], the book here[3], Stackoverflow has an overview of the whole system here[4].

You emit signals. Slots consume them. QObject::connect links the two. Queues are just queues in the traditional MQ sense. You don't use them in for, say, local GUI controls since it's generally a 1-1 unidirectional link (and if it's bi-directional, although I rarely need to do this, just ::connect( a,b,SLOT(),SIGNAL() ) then ::connect( b,a,SLOT(),SIGNAL() ). If you're still having problems read this[5]. If you have issues, that blog also has a preceding page which has a comprehensive analysis of the underpinnings of the entire slot/signal system in QT. If you still have problems, get on IRC and someone will give you a hand. If you're having a major issue, contact me. If it's a quicky I'll lend a hand, if not I know a few absolutely spectacular HN engineers who I'd recommend in a heartbeat.

I'd be real curious as to what's you consider 'messy' about signals/slots is you're having re: slots/signals (I guess since I've used Moose's MOP with Perl 5 and CL they sort of came naturally to me). I have no affiliation with Trolltech/QT/Nokia/whoever-owns-whatever-now at all; I just think C++ is real easy to mess up, libraries are even easier and they did a way-above-average job with their code-base (not to mention, documentation, ecosystem, etc).

The setup you want to use for cross-platform is Qt5.x + QML 2.x + QtQuick 2.x (aka QtQuickControls 2 in newer versions). There's licensing issues on some of the fancy-schmancy widgets but most of the things follow LGPL, so just dynamically link, follow the rules, and you won't get sued. If you're working on a legacy codebase (gcc2.95.3 hollaaaaa), don't try to force new-style QT into an old project, or your experience will be similar to @bwoj. 5.6(or there abouts) and up is where QML started to shine.

N.b. you don't have to use QTcreator. I find it satisfactory but that just might be years of Stockholm Syndrome. Most people coming from the C++/MFC (or C++/WTL/ATL/COM/WinAPI world) are more comfortable with Visual Studio. No problem, the 'standard' procedure is just to do what you would do with any .sln and split GUI into another project.

----

[0] https://www.qt.io/qt-essentials-qt-quick-for-c-developers/

[1] http://doc.qt.io/qt-5/qtquick-codesamples.html

[2] http://doc.qt.io/qt-5/qmlapplications.html

[3] https://qmlbook.github.io/assets/qt5_cadaques.pdf

[4] http://stackoverflow.com/a/19837895

[5] https://woboq.com/blog/how-qt-signals-slots-work-part2-qt5.h...


Thanks a lot for the explanation and the links, I'm going to go through all this.

I think the signal/slot system of Qt is very well designed actually (I had no problem with it in pure C++ applications), it's just my implementation while using QML which ended up being messy. I also had to refactor some parts due to Android not liking slots in one thread and signal emitter in another. Also it seems signals were sent in a particular order on desktop and a different order on Android. That's why I'm looking for a clean architecture which would allow me to know and reason about what's happening in the application.


[quote] I also had to refactor some parts due to Android not liking slots in one thread and signal emitter in another. [/quote]

Ouch? Worry free passing of signals/slots between threads is a feature of desktop Qt that I use and abuse all the time. I've even done a GUI-less daemon that used QtCore and abused signals/slots to communicate between threads. You mean it doesn't work on the mobile versions?




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

Search: