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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章