使用Python从QML中动态创建的列表访问数据
我在QML中有一个列表,并在listView对象中显示它。我需要在按下按钮时从python访问这些数据。在Python中,我创建了一个QStringListModel对象,并使用setContextProperty将其绑定到QML中的listModel。我可以看到在QML中按照预期创建和显示的列表,但是当我想从python访问数据时,列表是空的。代码如下: QML: Python:使用Python从QML中动态创建的列表访问数据,python,qml,pyqt5,qstringlistmodel,Python,Qml,Pyqt5,Qstringlistmodel,我在QML中有一个列表,并在listView对象中显示它。我需要在按下按钮时从python访问这些数据。在Python中,我创建了一个QStringListModel对象,并使用setContextProperty将其绑定到QML中的listModel。我可以看到在QML中按照预期创建和显示的列表,但是当我想从python访问数据时,列表是空的。代码如下: QML: Python: import sys from PyQt5.QtCore import QUrl, QStringListMode
import sys
from PyQt5.QtCore import QUrl, QStringListModel
from PyQt5.QtWidgets import QApplication
from PyQt5.QtQuick import QQuickView
app = QApplication(sys.argv)
view = QQuickView()
view.setSource(QUrl("main.qml"))
pyList = QStringListModel()
view.rootContext().setContextProperty("myModel",pyList)
print(pyList.stringList())
print(pyList.rowCount())
view.show()
print("Done!")
sys.exit(app.exec_())
我的印象是,当我们使用python绑定时,在python中创建的对象被绑定到QML对象。因此,如果QML列表有数据(在UI中动态创建),python列表应该自动填充该数据吗?我遗漏了什么?您假设,由于您通过与ListModel同名的setContextProperty()传递的模型是相同的,因此不会,相反,它会导致程序不稳定,因为QML与这两个名称重叠。相反,您必须在python中创建一个模型并将其导出,但由于您还希望与QML交互,因此最好导出一个将模型作为qproperty的QObject。不要使用findChild、findChildren来获取python中的QML元素,必须执行与将元素从python导出到QML相反的操作 考虑到上述情况,除了可以从QML调用的插槽之外,我还实现了一个具有qproperty模型的Manager类。为了避免代码复杂化,我使用QStandardItemModel类作为模型的基础,QStringListModel是一个只读模型,因此它不适用于这种情况 main.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_())
main.qml
import QtQuick 2.0
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.3
Rectangle{
id: root
width:800
height:600
ColumnLayout{
anchors.fill: parent
ListView {
id: listView
Layout.alignment: Qt.AlignLeft
Layout.fillHeight: true
model: manager.model
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
}
}
}
Button{
Layout.alignment: Qt.AlignCenter
text: "click me"
onClicked: manager.on_clicked()
}
}
Component.onCompleted:{
manager.model.addElement("Gray", "gray")
manager.model.addElement("Red", "red")
manager.model.addElement("Blue", "blue")
manager.model.addElement("Green", "green")
}
}
我建议你阅读更详细的解释 从这里我们看到,您的列表是空的,您在哪里添加项目?显示
sendChar
的实现以及您的委托
。开发人员喜欢帮助他们复制粘贴代码,看看有什么问题。嘿,我把代码改成了一个简短的例子。我在qml中有一个列表,但我无法从python访问它的数据。我是一个Qml新手,所以我不确定我在这里错过了什么!
import QtQuick 2.0
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.3
Rectangle{
id: root
width:800
height:600
ColumnLayout{
anchors.fill: parent
ListView {
id: listView
Layout.alignment: Qt.AlignLeft
Layout.fillHeight: true
model: manager.model
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
}
}
}
Button{
Layout.alignment: Qt.AlignCenter
text: "click me"
onClicked: manager.on_clicked()
}
}
Component.onCompleted:{
manager.model.addElement("Gray", "gray")
manager.model.addElement("Red", "red")
manager.model.addElement("Blue", "blue")
manager.model.addElement("Green", "green")
}
}