【问题标题】:Interacting with delegated QML Component in Repeater from C++从 C++ 与中继器中的委托 QML 组件交互
【发布时间】:2015-08-21 07:15:23
【问题描述】:

我无法从 C++ 访问中继器中的委托 QML 组件。请在下面找到代码。谢谢。

main.cpp

#include <QApplication>
#include <QDebug>
#include <QQuickView>
#include <QQuickItem>

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    QQuickView view;
    view.setSource(QUrl(QStringLiteral("qrc:/Main.qml")));
    view.show();
    QQuickItem *object = view.rootObject();
    QObject *rectangle = object->findChild<QObject*>("rect1");

    if (!rectangle)
    qDebug() << "MyError: rectangle was not found";

    app.exec();
}

Main.qml

import QtQuick 2.4

Row {
    Repeater {
        model: 3
        Rectangle {
            width: 50; height: 50
            color: index %2 ? "black" : "white"
            objectName: "rect" + index
        }
    }
}

控制台输出:

MyError: rectangle was not found

【问题讨论】:

    标签: c++ qt qml repeater qqmlcomponent


    【解决方案1】:

    我已经在 C++ 中实现了自己的递归函数模板 'findChild' 函数。`

    template <class T>
    SearchType findChild(QQuickItem* object, const QString& objectName)
    {
            QList<QQuickItem*> children = object->childItems();
            foreach (QQuickItem* item, children)
            {
                if (QQmlProperty::read(item, "objectName").toString() == objectName)
                    return item;
    
                T child = findChild<QQuickItem*>(item, objectName);
    
                if (child)
                    return child;
        }
        return nullptr;
    }
    

    并将其称为默认函数。

    QQuickItem *object = view.rootObject();
    QQuickItem *rectangle = findChild<QQuickItem*>(object, "rect1");
    
    if (rectangle)
    {
        qDebug() << rectangle;
        qDebug() << rectangle->objectName();
    } 
    

    并获得输出:

    QQuickRectangle(0x2222b40, name="rect1", parent=0x22245b0, geometry=50,0 50x50)
    "rect1"
    

    【讨论】:

      【解决方案2】:

      如果您调用object-&gt;dumpObjectTree(),您将看到类似于以下控制台输出的内容:

      QQuickRow:: 
      QQuickRepeater:: 
          QQmlComponent::
      

      如您所见,对象树不包含作为专用 qobjects 的矩形。在我对 QML 方面的有限理解中,还有另一棵树包含所有可见的 qml 项目/组件。这些您至少可以通过 qml 中的 'children'-property 访问。为了证明这一点,我将您的 qml 文件更改为:

      Main.qml:

      Row {
          id: row
          Repeater {
              model: 3
              Rectangle {
                  width: 50; height: 50
                  color: index %2 ? "black" : "white"
                  objectName: "rect" + index
              }
      
          }
          Component.onCompleted: {
              console.log(row.children[0].objectName);
              console.log(row.children[1].objectName);
              console.log(row.children[2].objectName);
          }
      
      }
      

      产生以下输出:

      qml: rect0
      qml: rect1
      qml: rect2
      MyError: rectangle was not found
      

      当然,直接可访问性和索引取决于您的附加项目/组件。从这里开始,您可以编写自己的递归“findChild”函数并将结果对象公开给 C++。这里描述了如何:http://doc.qt.io/qt-5/qtqml-cppintegration-interactqmlfromcpp.html

      例如,您可以像这样在 qml 中实现“findChild”:

      function findChild(propertyName, propertyValue) {
          return findChildRecursivly(row, propertyName, propertyValue)
      }
      

      这个 qml 函数可以像 C++ 一样调用

      QVariant result;
      QMetaObject::invokeMethod(object, "findChild",
                                Q_RETURN_ARG(QVariant, result),
                                Q_ARG(QVariant, "objectName"),
                                Q_ARG(QVariant, "rect1"));
      rectangle = result.value<QObject *>();
      

      使用以下附加代码行:

      if (!rectangle)
      {
          qDebug() << "MyError: rectangle was not found";
      }
      else
      {
          qDebug() << rectangle;
          qDebug() << rectangle->objectName();
      }
      

      你会得到以下输出:

      QQuickRectangle(0x1c1beef, name = "rect1")
      "rect1"
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-01-21
        • 1970-01-01
        • 1970-01-01
        • 2010-10-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多