how to insert/edit QAbstractListModel in python and qml updates automatically?(如何在 python 和 qml 中自动插入/编辑 QAbstractListModel 更新?)
问题描述
我正在尝试插入/编辑从 pyqt5 中的 QAbstractListModel 子类化的 python 列表.这个 python 列表是在 qml 中 ListView 元素的 model 属性中读取的.我在 qml 中显示数据没有问题.当我尝试将新数据附加到 python 列表中时出现问题.
i am trying to insert/edit a python list that is subclassed from QAbstractListModel in pyqt5. this python list is read in the model property of ListView element in qml. i have no issues displaying the data in qml. problem arises when i try to append new data into the python list.  
以下是我目前所做的:
main.py:
import sys, model2
from PyQt5.QtCore import QUrl
from PyQt5.QtWidgets import QApplication
from PyQt5.QtQuick import QQuickView
class MainWindow(QQuickView):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.model = model2.PersonModel()
        self.rootContext().setContextProperty('PersonModel', self.model)
        self.rootContext().setContextProperty('MainWindow', self)
        self.setSource(QUrl('test2.qml'))
myApp = QApplication(sys.argv)
ui = MainWindow()
ui.show()
sys.exit(myApp.exec_())
model2.py
from PyQt5.QtCore import QAbstractListModel, Qt, pyqtSignal, pyqtSlot
class PersonModel(QAbstractListModel):
    Name = Qt.UserRole + 1
    Age = Qt.UserRole + 2
    personChanged = pyqtSignal()
    def __init__(self, parent=None):
        super().__init__(parent)
        self.persons = [
            {'name': 'jon', 'age': 20},
            {'name': 'jane', 'age': 25}
        ]
    def data(self, QModelIndex, role):
        row = QModelIndex.row()
        if role == self.Name:
            return self.persons[row]["name"]
        if role == self.Age:
            return self.persons[row]["age"]
    def rowCount(self, parent=None):
        return len(self.persons)
    def roleNames(self):
        return {
            Qt.UserRole + 1: b'name',
            Qt.UserRole + 2: b'age'
        }
    @pyqtSlot()
    def addData(self):
        self.beginResetModel()
        self.persons = self.persons.append({'name': 'peter', 'age': 22})
        self.endResetModel()
        print(self.persons)
    @pyqtSlot()
    def editData(self):
        print(self.model.persons)
test2.qml:
import QtQuick 2.6
import QtQuick.Controls 2.2
Rectangle {
    anchors.fill: parent
    color: "lightgrey"
    ListView {
        id: listExample
        anchors.fill: parent
        model: PersonModel
        delegate: Text {
            text: name + " " + age
        }
    }
    Button {
        width: 50
        height: 25
        anchors.bottom: parent.bottom
        text: "add"
        onClicked: {
            console.log("qml adding")
            PersonModel.addData()
        }
    }
    .
    .
    .
}
当我单击调用 model2.py 中的 addData 方法的添加按钮时发生错误.错误在于 rowCount 并且错误消息说 TypeError: object of type 'NoneType' has no len().我是否必须发出更改或传递一些索引和角色值,以便 qml 知道什么是新/旧并仅相应地反映更改?
error occurs when i click the add button which calls the addData method in model2.py. error lies in the rowCount and error message says TypeError: object of type 'NoneType' has no len(). do i have to emit the changes or pass in some index and role value so qml knows what is new/old and only reflect the changes accordingly?
非常感谢任何形式的指导!
any form of guidance is greatly appreciated!
推荐答案
你得到的错误是由下面这行代码引起的:
The error you get is caused by the following line of code:
self.persons = self.persons.append({'name': 'peter', 'age': 22})
这是因为 append 函数没有返回任何东西,所以它是为了将 None 分配给 self.persons
It is caused because the append function does not return anything, so it was meant to assign None to self.persons
要插入新数据,您必须调用 beginInsertRows() 和 endInsertRows() 来通知视图更改.
To insert new data you must call beginInsertRows() and endInsertRows() to notify the view of the change.
数据方法必须与文档中显示的相同,即必须具有以下格式:
the data method must be identical to that shown in the documentation, ie it must have the following format:
def data(self, index, role=Qt.DisplayRole):
与rowCount方法相同:
The same with the rowCount method:
def rowCount(self, parent=QModelIndex()):
我已经实现了 addPerson、editPerson 和 deletePerson 方法,它们分别添加、编辑和删除列表中的数据.我还在 .qml 中添加了必要的项目以便能够对其进行测试.
I have implemented the methods addPerson, editPerson and deletePerson that adds, edits and deletes a data from the list respectively. Also I added the necessary items to the .qml to be able to test it.
model2.py
from PyQt5.QtCore import QAbstractListModel, Qt, pyqtSignal, pyqtSlot, QModelIndex    
class PersonModel(QAbstractListModel):
    NameRole = Qt.UserRole + 1
    AgeRole = Qt.UserRole + 2
    personChanged = pyqtSignal()
    def __init__(self, parent=None):
        super().__init__(parent)
        self.persons = [
            {'name': 'jon', 'age': 20},
            {'name': 'jane', 'age': 25}
        ]
    def data(self, index, role=Qt.DisplayRole):
        row = index.row()
        if role == PersonModel.NameRole:
            return self.persons[row]["name"]
        if role == PersonModel.AgeRole:
            return self.persons[row]["age"]
    def rowCount(self, parent=QModelIndex()):
        return len(self.persons)
    def roleNames(self):
        return {
            PersonModel.NameRole: b'name',
            PersonModel.AgeRole: b'age'
        }
    @pyqtSlot(str, int)
    def addPerson(self, name, age):
        self.beginInsertRows(QModelIndex(), self.rowCount(), self.rowCount())
        self.persons.append({'name': name, 'age': age})
        self.endInsertRows()
    @pyqtSlot(int, str, int)
    def editPerson(self, row, name, age):
        ix = self.index(row, 0)
        self.persons[row] = {'name': name, 'age': age}
        self.dataChanged.emit(ix, ix, self.roleNames())
    @pyqtSlot(int)
    def deletePerson(self, row):
        self.beginRemoveColumns(QModelIndex(), row, row)
        del self.persons[row]
        self.endRemoveRows()
test2.qml
import QtQuick 2.6
import QtQuick.Controls 2.2
Rectangle {
    anchors.fill: parent
    color: "lightgrey"
    ListView {
        id: listExample
        anchors.fill: parent
        model: PersonModel
        delegate:
            Item {
            width: 200
            height: 60
            Row {
                Text {
                    width: 60
                    text:  name + " " + age
                    horizontalAlignment: Text.AlignHCenter
                    anchors.verticalCenter: parent.verticalCenter
                }
                Button{
                    width: 20
                    text: "+"
                    onClicked: PersonModel.editPerson(index, name, age+1)
                }
                Button{
                    width: 20
                    text: "-"
                    onClicked: PersonModel.editPerson(index, name, age-1)
                }
                Button{
                    width: 20
                    text: "X"
                    onClicked: PersonModel.deletePerson(index)
                }
            }
        }
    }
    Button {
        width: 50
        height: 25
        anchors.bottom: parent.bottom
        anchors.right: parent.right
        text: "add"
        onClicked: {
            console.log("qml adding")
            PersonModel.addPerson("luis", 22)
        }
    }
}
.py
@pyqtSlot(int, str, int)
def insertPerson(self, row, name, age):
    self.beginInsertRows(QModelIndex(), row, row)
    self.persons.insert(row, {'name': name, 'age': age})
    self.endInsertRows()
.qml
 PersonModel.insertPerson(2, "luis", 1111)
                        这篇关于如何在 python 和 qml 中自动插入/编辑 QAbstractListModel 更新?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:如何在 python 和 qml 中自动插入/编辑 QAbstractListModel 更新?
				
        
 
            
        - 使用公司代理使Python3.x Slack(松弛客户端) 2022-01-01
 - 我如何透明地重定向一个Python导入? 2022-01-01
 - 计算测试数量的Python单元测试 2022-01-01
 - 如何使用PYSPARK从Spark获得批次行 2022-01-01
 - 检查具有纬度和经度的地理点是否在 shapefile 中 2022-01-01
 - YouTube API v3 返回截断的观看记录 2022-01-01
 - 我如何卸载 PyTorch? 2022-01-01
 - CTR 中的 AES 如何用于 Python 和 PyCrypto? 2022-01-01
 - ";find_element_by_name(';name';)";和&QOOT;FIND_ELEMENT(BY NAME,';NAME';)";之间有什么区别? 2022-01-01
 - 使用 Cython 将 Python 链接到共享库 2022-01-01
 
