Calling QML functions from C++ [SOLVED]
-
The first way gave an error:
ASSERT failure in QList<T>::at: "index out of range"
I try to do it like this:
@QObject * object = engine.rootObjects().value(0)->findChild<QObject*>("algoShow");
QMetaObject::invokeMethod(object, "insertText",
Q_ARG(QVariant, QVariant::fromValue(QString("Hello from c++!"))));@or like this:
@QObject * object = engine.findChild<QObject*>("algoShow");@
and QML:
@function insertText(msg) {
console.log(msg);
}@But nothing happened, i think that function was not invoked..
-
bq. ASSERT failure in QList<T>::at: “index out of range”
Do you have any QML created at the time you try that? If you don't have the first element in root objects, then you probably don't have anything at all, you HAVE TO HAVE root before you can have anything else. You are probably doing it before any QML is loaded.
The reason you don't get the out of range error with value() is because this method returns a default constructed value if nothing is found, so you get a null pointer, which is why invoke method doesn't do anything.
Make sure you have your QML loaded before you try to access it.
@engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); // or whatever your main QML file is@
-
Oh, i loaded main,qml, right like you wrote. But then i also created two qml files directly from qml document, in this way:
in main.cpp I load main.qml:
@Manager manager;
engine.load(QUrl(mainPath));
object = engine.rootObjects().value(0);
engine.rootContext()->setContextProperty("myObj", &manager);@in main.qml I load the second qml file :
@ApplicationWindow {
id: mainWindow
property variant win;button {
...
onClicked: {var component = Qt.createComponent("qrc:/Smejnost.qml"); win = component.createObject(mainWindow); win.show(); }
}}@
Maybe you can suggest a better way, how to load and manage qml files. I'm just a beginner :)
-
Well, you don't honestly expect that you will be able to find the object in C++ main() before it was created in QML, right?
There is nothing wrong with the way you create the Smejnost component, and regardless of the style of creation, you will always need to have it created before you can locate it with findChild().
You just have to put your call from C++ to QML in the proper "spot", not simply in main, because it will run immediately after the main component is set, before you have the chance to create extra components from QML.
But if you really want to put it in main, you can use a signal, add a signal to the ApplicationWindow, in main() find the main object and connect that signal to a free function or lambda which wraps the findChild() and inkoveMethod() call, and from QML emit the signal when Smejnost has been created. This way you will attempt to find the target component only after it is created.
-
-
YES ! I just load qml file like in qt tutorial, and it's worked !
@QQmlEngine engine;
QQmlComponent component(&engine, QUrl(QStringLiteral("qrc:/Algo_Show.qml")));
QObject *object = component.create();
QVariant msg = "Hello from C++";
QMetaObject::invokeMethod(object, "insertText",
Q_ARG(QVariant, msg));
@Like i said before, i'm just a begginer ) But the problem solved! Thanks.
-
Yes, you could have created the QML object from C++ as well. All this is for the sake of getting a test to work I guess, you will have to figure out how to lay out your actual application so you avoid the "chicken or egg" paradox.
And since you already use Qt, you might as well be using QFile instead of fstream.