QQuickView vs QDeclarativeView
-
Hi,
I'm developing a modular desktop environment with a QML frontend and C++ backend, intended for use on Linux desktops.
The desktop itself doesn't provide much functionality, except the ability to manage plugins, which are shared libraries which contain QML files as resources. All the actual functionality will be integrated into these.
The more I read Qt documentation, the more I doubt my approach is the optimal one.
Currently I'm using QPluginLoader to load the plugins, and a QQuickView as my QML scene.
After loading the plugin, the resources inside (such as QML files) become available and my approach then requires a messy signaling back and forth to create the QML from using Qt.createComponent inside QtQuick and then connecting the signals/slots to the relevant C++ class.Ideally, after loading the plugin with QPluginLoader, I would then create a QQuickItem from the QML contained inside it, connect signals/slots to the relevant c++ class and finally insert it in the QQuickView.
This is where my current approach gets messy - after loading the plugin, I send a signal to the QML frontend which creates the QML file using Qt.createComponent, after which I send a signal back to create the signal/slot connections. It's pretty messy.
So after googling for a while, it would appear that instead of a QQuickView, the QDeclarativeView class is better suited for my needs? (This class is available to me, though not present in my documentation for Qt5.1?)
An additional concern for me would be memory use and general performance since using a QDeclarativeView appears to require additional modules (gui).
I could use some guidance here :)
Thanks for reading
-
You are mistaken. QDeclarativeView is the old compatibility class, which istantiates QtQuick 1.0/ 1.1 scenes. It will not work with QtQuick 2.0 and newer. Also the point about performance is mostly wrong: QtQuick 1 uses raster engine to paint, which is very fast in some use cases, while QtQuick 2 uses OpenGL, which is ultra fast in most ;)
Would your situation improve if changed the way you load stuff? Maybe instead of providing a plugin with QML files embedded, create QRC resource as an external file, and load that instead?
-
Hi, thanks for your answer!
I'm reassured and glad to know QQuickView is the way to go, though I still need to figure out the optimal way how to achieve what I want.
I'd rather keep everything contained inside the plugins instead of messing around with external resource files.
Because my original post could have been clearer, here's exactly what I would like to achieve;
-
Application loads a shared library, which has a QML file integrated as a resource. These are defined with a prefix which is identical to the IID of the plugin;
-
Immediately after loading the plugin, it would look for the availability of this QML file (using QResource) and if it's present, create it as an unparented QQuickItem from the C++ side;
-
Connect the signals/slots from this QML file to C++ slots from this plugin;
-
Insert the QQuickItem into the QQuickView. (reparent it to the rootObject?)
As far as I can tell, the only way to create the QML component is to do it from within QtQuick (using Qt.createComponent) and that's precisely what i would like to avoid because it means I would need to 'switch' back and forth between QtQuick and C++ several times (using signals)
Here's my current approach:
-
Load plugin, check for availability of QML file within;
-
Send path of resource to QtQuick through a signal, and create the component there (with Qt.createComponent). When done, send signal back to C++ backend
-
Use QQuickView.findChild to look for the objectName of this component and retrieve a QQuickItem;
-
Connect slots and signals;
-
Send signal back to QtQuick to notify it's ready and continue initialisation of plugin.
Since some of the plugins also require the use of SQL (with a ListView or GridView in QtQuick), there needs to be an additional step using QQmlContext.setContextProperty in there in there as well.
So, as you can imagine, I need several extra signals and slots on both sides to get it working, in addition to storing the currently processed plugin as a tempory variable since this process can't be contained within a single scope.
Thanks for reading once again!
-
-
Thanks, this is a bit clearer now. I have not tried instantiating the whole QML scene from c++ in a way you envision, but creating new components in C++ (when the engine is working already) is possible and also quite easy.
I have an example on how it is done (you can also look it up in the documentation), but the example from my project is quite involved. So, put your seatbelts on :)
In my case, I am creating new QML components from inside of my custom QtQuickItem derivative. Component creation is asynchronous, so you need some signals and slots, or at least defer instantiation and reparenting as I do.
Here I prepare my component - "link":https://github.com/sierdzio/closecombatfree/blob/master/src/qmlBase/ccfqmlbasescenario.cpp#L30. Next step is to instantiate and reparent (warning: sometimes QObject::setParent() does not work, my solution seems to work reliably) - "link":https://github.com/sierdzio/closecombatfree/blob/master/src/qmlBase/ccfqmlbasescenario.cpp#L420.
Feel free to look through my project, it should work out of the box in Qt Creator.
-
Hi,
Thanks for the tip! I derived from your source that using QQmlComponent was the way to go.
I have implemented that now, and added QMetaObject::connectSlotsByName to boot, so now everything - loading the plugin, creating the QML, connecting slots and signals between the two - is handled in just one method. Very nice!
Now all I need is just slot names that correspond with the signal in the QML file.