How to set a pure C++ object instance in a QQuickItem
-
Hi Guys.....I have
QtApp
& a pure C++ library. The C++ library exposes a one simple class calledMyCppLibApiClass
. TheQtApp
has a class which is embedded onmain.qml
. Following is the class://MyQuickItem.h class MyQuickItem : public QQuickItem { MyQuickItem(); SetCppObject(MyCppLibApiClass cppObject); MyCppLibApiClass m_cppObject; }
Following the
qml
code for thequick item
://MainPage.qml import MyQuickItem 1.0 MyQuickItem { id: myQuickItemID visible: true objectName: "myQuickItem" }
Following is my
main.cpp
showing I load theqml
item://main.cpp qmlRegisterType<MyQuickItem>("MyQuickItem", 1, 0, "MyQuickItem"); QQmlApplicationEngine engine; engine.load(QUrl(QStringLiteral("qrc:/qml/main.qml"))); return app.exec();
MyQuickItem
needs access toMyCppLibApiClass
instance. How do a I get a valid instance toMyQuickItem
inmain.cpp
& call SetCppObject() on it ? I need to set an object ofMyCppLibApiClass
as member inMyQuickItem
. I can do this using a setter method likeSetCppObject
. But, first of all I need to get a valid instance toMyQuickItem
. So How to get access toMyQuickItem
inmain.cpp
?I have searched quite a lot before asking this question. I read through this link. But it describes how to set properties with only Qt types like QString & others.Appreciate suggestions to this..
-
Hi,
The code sample uses
setProperty
as an example of method to call. You have the object at hand so call the methods you need on it. -
@Nelson_Piquet You can also instantiate the
MyCppLibApiClass
inmain.cpp
then set it as a context property which will then be accessible fromMyQuickItem
in QML.
Something likeqmlRegisterType<MyQuickItem>("MyQuickItem", 1, 0, "MyQuickItem"); MyCppLibApiClass myClass; QQmlApplicationEngine engine; engine.load(QUrl(QStringLiteral("qrc:/qml/main.qml"))); engine.rootContext()->setContextProperty("myObj", &myClass); // Access myObj from QML return app.exec();
More info here:
http://doc.qt.io/qt-5/qtqml-cppintegration-contextproperties.html -
@Nelson_Piquet You can also instantiate the
MyCppLibApiClass
inmain.cpp
then set it as a context property which will then be accessible fromMyQuickItem
in QML.
Something likeqmlRegisterType<MyQuickItem>("MyQuickItem", 1, 0, "MyQuickItem"); MyCppLibApiClass myClass; QQmlApplicationEngine engine; engine.load(QUrl(QStringLiteral("qrc:/qml/main.qml"))); engine.rootContext()->setContextProperty("myObj", &myClass); // Access myObj from QML return app.exec();
More info here:
http://doc.qt.io/qt-5/qtqml-cppintegration-contextproperties.html@p3c0 @SGaist Thanks a lot for your attention. p3c0's answer suggests how to make
MyCppLibApiClass
recognisable on qml side. but, I cannot take this approach because this requires to makeMyCppLibApiClass
inherited byQObject
if I am correct.MyCppLibApiClass
comes from a pure C++ library & I cannot afford to introduce Qt into it. But My primary question is slightly different here. My question is: How to get a valid instance ofMyQuickItem
& callSetCppObject
which accepts a pure Cpp obejct i.e.MyCppLibApiClass
? I have updated my question & sample code in the question to make it clearer -
@Nelson_Piquet So as said earlier in the last post use
findChild
to get access to QML instance on C++ side. Now once you get this object call theSetCppObject
function and passcppObject
to it. -
@Nelson_Piquet So as said earlier in the last post use
findChild
to get access to QML instance on C++ side. Now once you get this object call theSetCppObject
function and passcppObject
to it.@p3c0 I found that just doing a
findChild
does not give me access toSetCppObject
. Looks like I have to cast it toMyQuickItem
to get access toSetCppObject
. Following compiles:QQuickView view; view.setSource(QUrl::fromLocalFile("main.qml")); QObject *object = view.rootObject(); QObject *rect = object->findChild<QObject*>("MyQuickItem"); MyQuickItem* quickItemObj = qobject_cast<MyQuickItem*>(rect); quickItemObj->SetCppObject(theCppObject);
But
qobject_cast
returns me a null pointer.Q_OBJECT
macro is included inMyQuickItem
class MyQuickItem : public QQuickItem { Q_OBJECT public: MyQuickItem(); }
Should I do something in
MyQuickItem
class to get a valid pointer toMyQuickItem
? Or pls correct me if I am going wrong here -
@Nelson_Piquet The object name that
findChild
accepts is case sensitive. I see a mismatch between this and your first post. ie.myQuickItem
andMyQuickItem
are totally different.But qobject_cast returns me a null pointer.
Probably because the object was not found at first.
-
@Nelson_Piquet The object name that
findChild
accepts is case sensitive. I see a mismatch between this and your first post. ie.myQuickItem
andMyQuickItem
are totally different.But qobject_cast returns me a null pointer.
Probably because the object was not found at first.
@p3c0 Thanks for point that out. I corrected the id. Also, the
main.qml
path I inputted was not the full path. It needs to be like so:qrc:/qml/main.qml
. After applying aqobject_cast
& I get a pointer toMyQuickItem
.But when I try to access
SetCppObject
, it crashes reporting an error which says :QQuickView does not support using windows as a root item. If you wish to create your root window from QML, consider using QQmlApplicationEngine instead.
But its a separate issue. I will read a little & put a separate question for that. Thanks a lot for helping until here. -
Maybe a silly question but do you really need a QQuickItem based wrapper ? Wouldn't a simple QObject wrapper do the work ?
-
@p3c0 Thanks for point that out. I corrected the id. Also, the
main.qml
path I inputted was not the full path. It needs to be like so:qrc:/qml/main.qml
. After applying aqobject_cast
& I get a pointer toMyQuickItem
.But when I try to access
SetCppObject
, it crashes reporting an error which says :QQuickView does not support using windows as a root item. If you wish to create your root window from QML, consider using QQmlApplicationEngine instead.
But its a separate issue. I will read a little & put a separate question for that. Thanks a lot for helping until here.@Nelson_Piquet As the error says
QQuickView
can only load root element of QML types that inheritsItem
whereas QQmlApplicationEngine loads root elementsWindow
andApplicationWindow
. -
Maybe a silly question but do you really need a QQuickItem based wrapper ? Wouldn't a simple QObject wrapper do the work ?
@SGaist I really need a QQuickItem based wrapper. it is embedded in qml. I am not sure of how to make it work as a QObject wrapper. but, now I've reached a point with all the help where I am able to retrieve the object of
MyQuickItem
. But now,MyQuickItem
's constructor gets called twice which is not what I need.......aahh !! Following is mymain.cpp
int main(int argc, char *argv[]) { QQmlApplicationEngine engine; qmlRegisterType<MyQuickItem>("MyQuickItem", 1, 0, "MyQuickItem"); QQuickView view; //Mainpage.qml is where MyQuickItem is located. Its sort of a child page of main.qml view.setSource(QUrl(QStringLiteral("qrc:/qml/pages/MainPage.qml"))); QObject *object = view.rootObject(); QObject *rect = object->findChild<QObject*>("myQuickItem"); //pls note that myQuickItem is the object name MyQuickItem* quickItem = qobject_cast<MyQuickItem*>(rect); quickItem->SetCppObject(theCppObject); engine.load(QUrl(QStringLiteral("qrc:/qml/main.qml"))); return app.exec(); }
My doubt is that
view.setSource
might need to be avoided but not sure how -
@Nelson_Piquet There is no need to load 2 QML files separetely. This is going to create 2 windows and thus complicate. Just load your main QML using QQuickView or QQmlApplicationEngine and from there load other QML files.
-
@Nelson_Piquet There is no need to load 2 QML files separetely. This is going to create 2 windows and thus complicate. Just load your main QML using QQuickView or QQmlApplicationEngine and from there load other QML files.
@p3c0 What should I change in my
main.cpp
to avoid loading the files twice ? If I dont callview.setSource
, I will not get hold of the child object. If dont callengine.load
, I cannot load mymain.qml
. How should I change mymain.cpp
. Since this question is a separate issue, I have posted a new question in this forum here -
About the QObject wrapper, unless I misunderstood, you only want to act on your MyCppLibApiClass and not paint anything related to it thus the QObject wrapper can be used without any dependency on a visual element.
-
About the QObject wrapper, unless I misunderstood, you only want to act on your MyCppLibApiClass and not paint anything related to it thus the QObject wrapper can be used without any dependency on a visual element.
@SGaist understood. thanks