使用Python访问QML中动态创建的列表中的数据

2024-04-26 04:15:20 发布

您现在位置:Python中文网/ 问答频道 /正文

我在QML中有一个列表,并将其显示在listView对象中。我需要在按下按钮时从python访问这些数据。在Python中,我创建了一个QStringListModel对象,并使用setContextProperty将其绑定到QML中的listModel。我可以看到在QML中按预期创建和显示的列表,但是当我想从python访问数据时,列表是空的。代码如下:

质量管理:

import QtQuick 2.0
import QtQuick.Controls 2.3

Rectangle{
    id: root
    width:800
    height:600

    ListView {
        id: listView
        x: 476
        y: 64
        width: 110
        height: 160
        model: myModel
        ListModel {
            id: myModel
            ListElement {
                name: "Grey"
                colorCode: "grey"
            }

            ListElement {
                name: "Red"
                colorCode: "red"
            }

            ListElement {
                name: "Blue"
                colorCode: "blue"
            }

            ListElement {
                name: "Green"
                colorCode: "green"
            }
        }
        delegate: Item {
            x: 5
            width: 80
            height: 40
            Row {
                id: row1
                Rectangle {
                    width: 40
                    height: 40
                    color: colorCode
                }

                Text {
                    text: name
                    anchors.verticalCenter: parent.verticalCenter
                    font.bold: true
                }
                spacing: 10
            }
        }
    }
}

Python:

^{pr2}$

我的印象是,当我们使用python绑定时,用python创建的对象被绑定到QML对象。因此,如果QML列表有数据(在UI中动态创建),python列表应该自动填充这些数据?我错过了什么?在


Tags: 数据对象nameimportid列表qmlwidth
1条回答
网友
1楼 · 发布于 2024-04-26 04:15:20

您假设,因为通过setContextProperty()传递的模型与ListModel同名,所以它会导致程序不稳定,因为QML与这两个名称重叠。相反,您必须在python中创建一个模型并将其导出,但是由于您还希望与QML交互,因此最好导出一个QObject,它将模型作为qproperty。要在python中查找子元素,必须使用dcqm的相反元素。在

考虑到上面的情况,除了可以从QML调用的slot之外,我实现了一个具有qproperty模型的Manager类。为了避免代码复杂化,我使用了QStandardItemModel类作为模型的基础,QStringListModel是一个只读模型,因此它不适用于本例。在

主.py

from enum import Enum
from PyQt5 import QtCore, QtGui, QtQuick

class ElementRoles:
    NameRole = QtCore.Qt.UserRole + 1000
    ColorRole = QtCore.Qt.UserRole + 1001

class ElementModel(QtGui.QStandardItemModel, ElementRoles):
    QtCore.Q_ENUM(ElementRoles)

    def __init__(self, parent=None):
        super(ElementModel, self).__init__(parent)
        roles = {
            ElementModel.NameRole: b'name',
            ElementModel.ColorRole: b'colorCode'
        }
        self.setItemRoleNames(roles)

    @QtCore.pyqtSlot(str, QtGui.QColor)
    def addElement(self, name, color):
        item = QtGui.QStandardItem()
        item.setData(name, ElementModel.NameRole)
        item.setData(color, ElementModel.ColorRole)
        self.appendRow(item)

class Manager(QtCore.QObject):
    def __init__(self, parent=None):
        super(Manager, self).__init__(parent)
        self._model = ElementModel()

    @QtCore.pyqtProperty(QtCore.QObject, constant=True)
    def model(self):
        return self._model

    @QtCore.pyqtSlot()
    def on_clicked(self):
        print("count:", self._model.rowCount())
        for row in range(self._model.rowCount()):
            it = self._model.item(row)
            print("row:", row)
            for role, name in self._model.roleNames().items():
                print("role:", name, "data:", it.data(role))

if __name__ == '__main__':
    import os
    import sys
    app = QtGui.QGuiApplication(sys.argv)
    manager = Manager()
    view = QtQuick.QQuickView()
    file = os.path.join(os.path.dirname(os.path.realpath(__file__)), "main.qml")
    view.rootContext().setContextProperty("manager", manager)
    view.setSource(QtCore.QUrl.fromLocalFile(file))
    view.show()
    sys.exit(app.exec_())

主.qml

^{pr2}$

我建议您阅读my another answer以获得更详细的解释。在

相关问题 更多 >