【问题标题】:I have multiple qml Files that get pushed via StackView. How do I connect them to C++我有多个通过 StackView 推送的 qml 文件。如何将它们连接到 C++
【发布时间】:2017-06-10 10:01:37
【问题描述】:

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

  • 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 // 主屏幕之后的随机 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)));
    

【问题讨论】:

  • secondframe.qml 如何访问堆栈对象?我有一个带有 Stackview 的应用程序,其中有 n 个页面。我需要从一页导航到另一页。我该怎么做?

标签: c++ qt qml interaction stackview


【解决方案1】:

比进入 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")}
    }
    

【讨论】:

  • 非常感谢!!!你是编程重量级冠军,也是一个非常漂亮的人。我很高兴这很好用。感谢您花时间研究我的问题
  • 为了告诉你这不是只有重量级编程冠军知道的秘密,我向你展示了全能的 Qt 文档:doc.qt.io/qt-5/qtqml-cppintegration-interactqmlfromcpp.html
  • 正在进行一些工作以使此特定文档更易于访问/发现,但我认为听听用户的想法仍然是件好事;如何改进文档,他们是否能够找到它等等。总是欢迎提出建议:bugreports.qt.io
  • @Mailerdaimon 这实际上是我使用的页面,它对我的​​特定问题没有帮助。正如我所描述的,QObject::connect 无法让我访问启动时未加载的文件。通过 Kevins 将类传递给 QML 的解决方案,我能够与我想要的每个对象进行交互。可能是我在使用 ::connect 方法时出错了,但是无论如何帮助页面中没有包含 Kevin 的解决方案
  • OP:最好看看this page。 @Mitch 文档在每个版本之间不断改进。有时,它缺少的是某种“最佳实践”或“一般建议”。类似于this 但应用于快速主题(例如上下文属性与注册类型)的东西对新手非常有用。只是我的 0.02 美分。 :)
【解决方案2】:

将 qmls 压入堆栈后,对象将可访问。因此,当您发出一些信号时,当对象将在堆栈​​上时,解决方案可能如下所示:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-02-12
    • 1970-01-01
    • 1970-01-01
    • 2019-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多