问题
My Projects contains 6 qml Files: The main.qml opens a new ApplicationWindow and declares the toolbar. It also initalizes StackView with the initalItem homescreen.qml. On the Home Screen I have different buttons which open different qml Files, via stack.push("URL"). Besides the main.qml all Files start with Item{}. I've been able to connect signals from the main.qml and the home.qml. But I've been unable to access Objects that are deeper in the stack. I don't know if I hvae to change my .cpp code to access the other objects, or if I should change the Initalization of StackView, so that all Files are loaded and accessible at the beginning. Here is the code, broke down to the very basics:
main.qml
ApplicationWindow { Rectangle{ id: homeButton objectName: "homeButton" signal qmlSignal(string msg) MouseArea { onClicked: {stack.push({item:"qrc:/home.qml}); homeButton.qmlSignal("Hello")} } } StackView{ initalItem: "qrc:/home.qml" }
}
secondframe.qml // A randomw qml File that comes after the Home Screen
Item { Rectangle{ id: test objectName: "test" signal qmlSignal(string msg) MouseArea { onClicked: {stack.push({item:"qrc:/thirdframe.qml}); test.qmlSignal("Hello")} } } }
main.cpp
QApplication app (argc, argv); QQmlEngine enigne; QQmlComponent component(&engine, QUrl(QStringLiteral("qrl:/main.qml"))); QObject *object = componet.create(); QQmlComponent newcomponent(&engine, QUrl(QStringLiteral("qrl:/secondframe.qml"))); QObject *newobject = newcomponet.create(); MyClass myClass QObject *home = object->findChild<QObject*>("homeButton"); // I'm able to connect to every Object in the main.qml or home.qml QObject::connect(home,SIGNAL(qmlSignal(Qstring)), &myClass, SLOT(cppSlot(QString))); QObject *test = newobject->findChild<QObject*>("test"); // Can't connect to the Objects in secondframe.qml QObject::connect(test,SIGNAL(qmlSignal(Qstring)), &myClass, SLOT(cppSlot(QString)));
回答1:
A way better approach than to reach into the QML tree and pull out objects that might or might not be there is to provide C++ based API to QML.
Create a QObject based class that has the methods QML needs to be able to call as slots or
Q_INVOKABLE
class MyAPI : public QObject { Q_OBJECT public slots: void cppSlot(const QString &text); };
Create an instance of that and expose it to QML
MyAPI myApi; QQmlEngine engine; engine.rootContext()->setContextProperty("_cppApi", &myApi);
Use in QML as if "_cppApi" is an object id
MouseArea { onClicked: {stack.push({item:"qrc:/thirdframe.qml}); _cppApi.cppSlot("Hello")} }
回答2:
After pushing qmls on the stack, objects will be accessible. So when you emit some signal, when object will be on the stack, solution can look like this:
MyClass myClass
QObject *home = object->findChild<QObject*>("homeButton"); // I'm able to connect to every Object in the main.qml or home.qml
QObject::connect(home,SIGNAL(qmlSignal(Qstring)), &myClass, SLOT(cppSlot(QString)));
connect( myClass, MyClass::emitWhenQMLIsAlreadyOnTheStack, this, [this](){
QObject *test = newobject->findChild<QObject*>("test"); // Now you should be able to connect
QObject::connect(test,SIGNAL(qmlSignal(Qstring)), &myClass, SLOT(cppSlot(QString));
});
来源:https://stackoverflow.com/questions/41847939/i-have-multiple-qml-files-that-get-pushed-via-stackview-how-do-i-connect-them-t