Pulling QList from C++ to qml
-
Hello,
Last year I've used a QList<QObject*> inside QML by passing the list to through a QVariant to QML the following way:
@
QMetaObject::invokeMethod(rootObject(), "refreshData", Q_ARG(QVariant, QVariant::fromValue(qListOfQObjectPtr));
@
I have this working in a project without Q_DECLARE_METATYPE(MyClassInheritsQObject*) macro where it simply compiles.
In all other projects I have to use the macro or QVariant complains it doesn't know the type.I was wondering how it is possible that last year's project just works (and compiles up to today) without the metatype macro.
I'm using QObject* and I can call Q_INVOKABLE functions with it inside QML but there is no Q_DECLARE_METATYPE macro anywhere in the project (even searched with Notepad++ through all project files).How is it possible that QML knows my QObject subclass?
Btw: I'm also not having any custom QML items using registerType, it's just a plain Object subclass with some data and Q_INVOCABLE functions.Another issue I'm having is that it seems impossible to read from a QVariantList which contains QObject*:
QMetaObject::invokeMethod(rootObject(), "refreshData", Q_ARG(QVariant, myVariantList));
The QML function refreshData(arr) can access arr but nothing can be done with the variant (which contains a QObject*).
How can I call for example a Q_INVOCABLE function from the variant? -
Hi,
Function invocation on a QObject* in QML is pretty special - the function signature is matched as closely as possible by introspecting the methods reported by the object's metaobject, and then the matching method is invoked. Q_INVOKABLE like Q_SLOT etc makes the function available through the metaobject by registering it with the metaobject system.
Note that QList<QObject*> has definitely been declared as a metaobject by QML internally (since we use QList<QObject*> in various places, eg the implementation of the QtQuick Item's "children" property requires (IIRC) QList<QObject*> to be registered as a metatype already.
So, in short: QML doesn't know your QObject subclass. But, so long as you make your derived class' methods and properties available through the metaobject system (via Q_PROPERTY, Q_INVOKABLE, Q_SLOTS, Q_ENUM etc), QML is able to introspect instance objects' metaobjects and access those methods and properties.
Regarding the QVariantList issue: this is interesting, as I thought QVariantList was automatically converted to JavaScript array. If the variant containing the QObject* isn't being transformed into a JavaScript object wrapping a QObject*, then either something is going wrong (eg, unregistered type, bug, etc) or something else is going on. Are you able to call a C++ function from within the "refreshData" function, where that C++ function takes a QVariant arg and returns a QObject* value (and uses QVariant::fromValue<QObject*>(variant) to get it from the arg)?
Cheers,
Chris. -
Thank you for your reply.
So if do not need the Q_DECLARE_METATYPE macro if I return my pointer as QObject* but I do need the macro if I want to return MyClass* regardless whether my called functions are Q_INVOKABLE (or registrated through some other way) or not.With what I learned from this I was able to work around the QVariantList problem by simply sending the variant as a QObject* instead of MyClass*
@
myVariantList.append(QVariant::fromValue((QObject*)new DataContainer("data from myVariantList"))); QMetaObject::invokeMethod(rootObject() , "refreshData" , Q_ARG(QVariant, myVariantList) );
@
@
function refreshData(arrData)
{
myText.text = "";
for (var i = 0; i < arrData.length; ++i)
{
myText.text += arrData[i].getData() + "\n";
}
}//everything works :)
@I believe that if I want to be able to use the DataContainer class I need the Q_DECLARE_METATYPE macro to tell QVariant what it is but also a registration of the type with qmlRegisterType so that it actually works inside QML.
I will try this out later but I do not understand why everything just works with QObject* and why it doesn't with MyClass* since MyClass IS a QObject after all.http://doc.qt.nokia.com/4.7-snapshot/qdeclarativeengine.html#qmlRegisterType
-
I figured that I was missing an include somewhere so that in one project I had to do nothing while in the other my code just worked. After a search it appears that including qdeclarativecontext.h does the job.
So I need to put this macro in the .cpp file or include the qdeclarativecontext.h header.C:\Qt\4.8.0\src\declarative\qml\qdeclarativecontext.h (1 hits)
Line 110: Q_DECLARE_METATYPE(QList<QObject*>)