Some days ago I was writing about how to have mixed QML/C++ objects in a QML application for Igalia, but I faced a problem with the code that I had written. And the problem was that I needed to receive some events and from the QML elements I was loading. Retaking that code:
#define QML_PATH "/path/to/the/qml/files/" MyObject::MyObject(QDeclarativeItem *parent = 0) : QDeclarativeItem(parent) { QDeclarativeEngine engine; QDeclarativeComponent component(&engine, QUrl::fromLocalFile(QML_PATH "MyObject.qml")); QDeclarativeItem *rect = dynamic_cast(component.create()); rect->setParentItem(this); }
and being MyObject.qml something like:
Button { id: "myButton" text: "Do something cool" }
The natural way of connecting that button to some slot you are writing would be something like:
MyObject::MyObject(QDeclarativeItem *parent = 0) : QDeclarativeItem(parent) { QDeclarativeEngine engine; QDeclarativeComponent component(&engine, QUrl::fromLocalFile(QML_PATH "MyObject.qml")); QDeclarativeItem *item = dynamic_cast(component.create()); item->setParentItem(this); connect(item, SIGNAL(clicked()), this, SLOT(doCoolStuff())); }
Even if you do this, you are not getting any event in the QML button you declare. It behaves as it were a label or whatever, but the key is the engine. The engine must live while you need the events of the QML component. And the easiest way of getting that done is adding the engine as a private class attribute:
#ifndef MYOBJECT_H #define MYOBJECT_H #include #include #include class PostCapture : public QDeclarativeItem { Q_OBJECT // ... private slots: void doCoolStuff(); private: QDeclarativeEngine m_engine; }; #endif
and of course removing the engine stack declaration from the constructor:
MyObject::MyObject(QDeclarativeItem *parent = 0) : QDeclarativeItem(parent) { QDeclarativeComponent component(&m_engine, QUrl::fromLocalFile(QML_PATH "MyObject.qml")); QDeclarativeItem *item = dynamic_cast(component.create()); item->setParentItem(this); connect(item, SIGNAL(clicked()), this, SLOT(doCoolStuff())); }
VoilĂ .
Of course, if you need to connect to any element that is not the root element, you can always forward the signals and properties from the QML root object or just use the QObject::findChild method to access the right component.
2 comments