Creating and changing qml objects from c++
-
Hi,
I create a component in c++ and use it as a sourceComponent for a Loader in QML, but - though setProperty returns true - I can't see the properties set by c++.The loader approach here is kind of a necessity, because in the end, the object to be created will be a complex, nested structure of qml files (I want to display math formulas). Most of these qml elements have loaders themselves (again: later to be set by c++), here I use the simplest qml (like an end branch of the nested structure).
I try it this way (shortened code):
main.cpp:
int main(int argc, char *argv[]) { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication app(argc, argv); QQmlApplicationEngine engine; engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); if (engine.rootObjects().isEmpty()) return -1; QObject *root = engine.rootObjects()[0]; // yet unused QQmlComponent* component = new QQmlComponent(&engine, QUrl(QStringLiteral("qrc:/ElementVariable.qml"))); QQuickItem *item = qobject_cast<QQuickItem*>(component->create()); qDebug()<< item->setProperty("text", "myNewText"); //returns true qDebug()<<item->setProperty("visible", true); //returns true engine.rootContext()->setContextProperty("EquationComponent", QVariant::fromValue<QQmlComponent*>(component)); return app.exec(); }
main.qml:
ApplicationWindow { visible: true width: 640 height: 480 Component { id: emptyComponent Item { } } Loader { objectName: "equationLoader" sourceComponent: typeof EquationComponent !== "undefined" ? EquationComponent : emptyComponent; width: childrenRect.width height: childrenRect.height } }
ElementVariable.qml:
import QtQuick 2.0 Rectangle { property alias text: textItem.text width: childrenRect.width height: childrenRect.height Text { id: textItem width: implicitWidth + 10 height: implicitHeight text: "textUnchanged" // this I want to change verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter } }
Result: I do see the element, but I don't see the text that is set in the main.cpp, I only see the Component's default text.
Any ideas?
-
@SeDi said in Creating and changing qml objects from c++:
I can't see the properties set by c++.
Where are you setting the properties in C++ which you would like see on QML ? Atleast I don't see that code here.
-
@dheerendra - thanks for your reply!
I set it right before the end of the main.cpp. It is a bit "hidden" because I have prepended it with qDebug()<<
qDebug()<< item->setProperty("text", "myNewText"); //returns true qDebug()<<item->setProperty("visible", true); //returns true
-
Here you are changing the properties of object called item. This object is not going to change your component.
-
@dheerendra - oh, I see. Thank you for your time and effort!
I have changed
engine.rootContext()->setContextProperty("EquationComponent", QVariant::fromValue<QQmlComponent*>(component));
into
engine.rootContext()->setContextProperty("EquationComponent", QVariant::fromValue<QQuickItem*>(item));
but I get the error:
"qrc:/main.qml:17:26: Unable to assign ElementVariable_QMLTYPE_2 to QQmlComponent"This seems understandable - it's called sourceComponent: after all.
Having reverted the above idea (back to setting the component, not the item) I have also tried to set the properties on the component - doesn't work either:
qDebug()<< component ->setProperty("text", "myNewText"); //returns false qDebug()<<component ->setProperty("visible", true); //returns false
It appears that I might have a misconception about Components/Items and that I lack sufficient knowledge about the Loader QML element.
- is a Component more like a template / a class?
- is an Item its realisation, like an actual object?
- How can I "force-feed" the Loader from c++ with a specific Object created from there?
-
Yes component is like class. Once done you can’t change. you can change properties of object. You can specify the properties while loading. You can check documentation for this.
-
Thank you very much! That solved it. The creation process is being done automatically by the Loader in QML. It didn't make sense to make a second and unrelated "component->create()" in c++. I have to set the Component first and then get the Item from the Loader via property("item") afterwards.
Here's the code involved:
loader->setProperty("sourceComponent", QVariant::fromValue<QQmlComponent*>(component)); QQuickItem* loaderItem = qvariant_cast<QQuickItem*>(loader->property("item")); loaderItem->setProperty("text", "myNewText");
-
NO need to set the property from C++ by getting item. You can do something like
Loader { sourceComponent: EquationComponent; text: "PthinkS" }