如何从 C++ 访问 QML ListView 委托项目?

Posted

技术标签:

【中文标题】如何从 C++ 访问 QML ListView 委托项目?【英文标题】:How to access QML ListView delegate items from C++? 【发布时间】:2016-04-21 10:57:49 【问题描述】:

Listview 中,我使用“delegate”弹出了 100 个项目,假设 listview 已经显示填充值。 现在我想从 C++ 中提取 QML 列表视图中已经显示的值。如何做到这一点? 笔记: 我无法直接访问数据模型, 因为我正在使用 隐藏 变量在委托中进行过滤

        /*This is not working code, Please note,
        delegate will not display all model data.*/
        ListView
        
        id:"listview"
           model:datamodel
           delegate:
                      if(!hidden)
                      
                        Text        
                        text:value
                      
                    

        


 //Can I access by using given approach?
 QObject * object =   m_qmlengine->rootObjects().at(0)->findChild<QObject* >("listview");

//Find objects
const QListObject& lists = object->children();

//0 to count maximum
//read the first property
QVarient value =  QQmlProperty::read(lists[0],"text");

【问题讨论】:

你应该至少从一个有效的代码开始。此外,您应该尽量减少从 C++ 到 QML 的访问,在这种情况下肯定不会。如果您想要 C++ 端的模型数据,请使用 C++ 模型。 我在做自动化测试,我无法使用模型数据进行验证,所以在qml中显示列表视图后,我需要将qml中的数据提取到C++并进行验证。 我怀疑它是否会像您期望的那样工作,您将有更好的机会在 QML 中迭代列表视图并将文本传递给插槽函数将文本发送到 C++。 由于我在做自动化测试,我无法编辑/触摸 qml,而是使用 qml 插件,这样应用程序就不会受到自动化测试代码的干扰。 在 QML 中进行 QML 测试:doc.qt.io/qt-5/qtquick-qtquicktest.html 【参考方案1】:

您可以使用 objectName 属性 在 QML 中搜索特定项目。我们来看一个简单的 QML 文件:

//main.qml
Window 
    width: 1024; height: 768; visible: true
    Rectangle 
        objectName: "testingItem"
        width: 200; height: 40; color: "green"
    

在 C++ 中,假设 engine 是加载 main.qml 的 QQmlApplicationEngine,我们可以通过使用 QObject::findChild 从 QML 根项搜索 QObject 树轻松找到 testingItem

//C++
void printTestingItemColor()

    auto rootObj = engine.rootObjects().at(0); //assume main.qml is loaded
    auto testingItem = rootObj->findChild<QQuickItem *>("testingItem");
    qDebug() << testingItem->property("color");

但是,此方法无法找到 QML 中的所有项目,因为某些项目可能没有 QObject 父级。例如ListViewRepeater中的代表:

ListView 
    objectName: "view"
    width: 200; height: 80
    model: ListModel  ListElement  colorRole: "green"  
    delegate: Rectangle 
        objectName: "testingItem" //printTestingItemColor() cannot find this!!
        width: 50; height: 50
        color: colorRole
    

对于ListView 中的委托,我们必须搜索visual child 而不是子对象。 ListView 代表是 ListView 的 contentItem 的父级。所以在 C++ 中,我们必须先搜索ListView(使用QObject::findChild),然后使用QQuickItem::childItemscontentItem 中搜索委托:

//C++
void UIControl::printTestingItemColorInListView()

    auto view = m_rootObj->findChild<QQuickItem *>("view");
    auto contentItem = view->property("contentItem").value<QQuickItem *>();
    auto contentItemChildren = contentItem->childItems();
    for (auto childItem: contentItemChildren )
    
        if (childItem->objectName() == "testingItem")
            qDebug() << childItem->property("color");
    

【讨论】:

以上是关于如何从 C++ 访问 QML ListView 委托项目?的主要内容,如果未能解决你的问题,请参考以下文章

如何从 C++ 访问特定 QML 控件的事件

QML , 如何从另一个 qml 访问元素

如何从 QML 中的列表视图访问 currentItem 的角色?

如何在 QML 中访问 ListView 的 ListModel 的 ListElement 的映射委托数据?

Qt中使用QML和Listview的问题

如何从 C++ 代码将 QML 对象转换为 QQuickWindow?