PyQt (PySide) 各种查找 QML 子对象 (children) 方法大全

对 Grid 对象获取 children

"""e.g. qml snippet:
Grid {
    objectName: "my_grid"
    Button { text: "Button 1" }
    Button { text: "Button 2" }
    Button { text: "Button 3" }
}
"""

# engine = QQmlApplicationEngine()
# root = engine.rootObjects()[0]

grid = root.findChild(QObject, 'my_grid')  # type: QObject
children = grid.children()  # -> [QObject, QObject, QObject]

对 ListView, Repeater 对象获取 children

ListView, Repeater 的特点是有 delegate 属性和 model 属性. 其 children 的获取方法不同于 Grid.

我暂时没有找到准确的获取其 children 的方法, 花了几天时间, 网上查了很多资料都没有解决方案. 下面是我根据官方对它的属性描述想出来的 “邪门歪道” 的方法, 仅供参考!

"""e.g. qml snippet:
ListView {
    objectName: "my_listview"
    model: ListModel {
        ListElement { name: "Bill Smith" }
        ListElement { name: "John Brown" }
        ListElement { name: "Sam Wise" }
    }
    delegate: Button { text: model.name }
}

"""

# engine = QQmlApplicationEngine()
# root = engine.rootObjects()[0]

listview = root.findChild(QObject, 'my_listview')  # type: QObject

def get_children(view):
    """
    注: ListView 的 children() 返回的不是我们想要的子元素列表, 而是 [<QObject 
    xxx (不知道是什么子对象)>, <QAbstractListModel model>, <QObject delegate>]. 
    所以这个 children() 方法不能用.
    我们现在利用的是 currentIndex 和 currentItem 这两个属性, currentIndex 返回的
    是当前子元素的位置, currentItem 就是该位置的子元素 (也就是我们想要的元素). 
    我们通过遍历并切换 currentIndex, 来变相地要求 listview 切换当前子元素, 从而
    通过 currentItem 逐个取出.
    """
    count = view.property('count')  # -> 3
    children = []
    for i in range(count):
        view.setProperty('currentIndex', i)  # 强制切换 index.
        item = view.property('currentItem')  # type: QQuickItem
        children.append(item)
    return children


children = get_children(listview)
for child in children:
    # child 就对应了示例布局中的 Button, 打印其 text 属性就会显示 model.name 值.
    print(child.property('text'))
    # -> 'Bill Smith', 'John Brown', 'Sam Wise'

参考:

  • Qt 助手 QML > ListView
  • https://forum.qt.io/topic/53965/loop-through-the-delegate-of-listview/4
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章