connect(model, &ModelObject::somethingChanged, [=] {
// knead the data structures used for the UI-side data model into something much simpler
// used for the audio engine
audioQueue.push([... data ...] { update the engine with the new data });
});
and conversely from the engine to the UI thread ; Qt signals do not cut it as emitting them allocate, if only a few bytes. (Doing it naively with std::function doesn't cut it either - I use this instead to store these functions: https://github.com/jcelerier/smallfunction/blob/master/small... ; also, the audio threads feeds back those functions into the main thread after their execution so that any memory owned by the lambda ends up being freed here and not in the audio thread.)I found that the primitives for threading and message passing between threads didn't work that well for me (both in terms of what they provide and in terms of performance) so I ended up "bypassing" them a bit with my own threading code (that is, still using QThread and QMutex etc. but not using the signals and slots model).
Once I've done that and moved everything off of the main thread, things worked well, so that program is still in QtWidgets with C++ and still in use, but I felt that Qt didn't do a good job of making multithreading easy for me.
That said, I still like continue to use Qt so you can consider this a sort of mild endorsement from me, I guess.
you could argue that drawing text is not a problem that a framework should solve. yet they do, so there is no reason that a framework cannot solve the typical problems of audio applications and inter thread communication etc.