我有多个通过StackView推送的qml文件.我如何将它们连接到C ++ [英] I have multiple qml Files that get pushed via StackView. How do I connect them to C++

查看:250
本文介绍了我有多个通过StackView推送的qml文件.我如何将它们连接到C ++的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的项目包含6个qml文件:main.qml打开一个新的ApplicationWindow并声明工具栏.它还使用initalItem homescreen.qml来初始化StackView.在主屏幕上,我有不同的按钮,可通过stack.push("URL")打开不同的qml文件.除main.qml外,所有文件均以Item {}开头. 我已经能够连接来自main.qml和home.qml的信号.但是我一直无法访问堆栈中较深的对象.我不知道是否要更改.cpp代码以访问其他对象,还是应该更改StackView的Initalization,以便在开始时就可以加载和访问所有文件. 这是代码,细分为最基本的内容:

  • 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//主屏幕后出现一个随机w qml文件

    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)));
    

解决方案

一种比进入QML树并提取可能存在或可能不存在的对象更好的方法是为QML提供基于C ++的API.

>

  1. 创建一个基于QObject的类,该类具有QML需要能够作为插槽或Q_INVOKABLE

    调用的方法

    class MyAPI : public QObject
    {
        Q_OBJECT
    public slots:
        void cppSlot(const QString &text);
    };
    

  2. 创建该实例并将其公开给QML

    MyAPI myApi;
    QQmlEngine engine;
    engine.rootContext()->setContextProperty("_cppApi", &myApi);
    

  3. 在QML中使用,就像"_cppApi"是对象ID一样

    MouseArea {
         onClicked:  {stack.push({item:"qrc:/thirdframe.qml}); _cppApi.cppSlot("Hello")}
    }
    

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)));
    

解决方案

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.

  1. 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);
    };
    

  2. Create an instance of that and expose it to QML

    MyAPI myApi;
    QQmlEngine engine;
    engine.rootContext()->setContextProperty("_cppApi", &myApi);
    

  3. Use in QML as if "_cppApi" is an object id

    MouseArea {
         onClicked:  {stack.push({item:"qrc:/thirdframe.qml}); _cppApi.cppSlot("Hello")}
    }
    

这篇关于我有多个通过StackView推送的qml文件.我如何将它们连接到C ++的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆