I would like to pass a list of dictionaries from pyqt5 to qml where this list becomes the model
of ListView
element. The following code is what i have so far.
main.py
class MainWindow(QQuickView):
def __init__(self, parent=None):
super().__init__(parent)
self.model = model.PersonModel()
self.rootContext().setContextProperty('PersonModel', self.model)
self.rootContext().setContextProperty('MainWindow', self)
self.setSource(QUrl('main.qml'))
@pyqtSlot()
def personsList(self):
print(self.model.persons) # this prints the list of objects perfectly fine
return(self.model.persons)
.
.
.
main.qml
ListView {
id: listExample
anchors.fill: parent
model: MainWindow.personsList()
delegate: PersonDelegate { }
highlight: highlightComponent
highlightMoveDuration: 0
Component.onCompleted: {
console.log(">>>", MainWindow.personsList()) // returns undefined, but why??
}
}
model.py
from PyQt5.QtCore import QAbstractListModel, Qt, QModelIndex
class PersonModel(QAbstractListModel):
NAME_ROLE = Qt.UserRole + 1
AGE_ROLE = Qt.UserRole + 2
def __init__(self, parent=None):
super().__init__(parent)
self.persons = [
{'name': 'jon', 'age': 20},
{'name': 'jane', 'age': 25},
{'name': 'pete', 'age': 25},
{'name': 'winson', 'age': 25},
{'name': 'ben', 'age': 25},
{'name': 'jiahao', 'age': 25}
]
self.currentIndex = 0
def data(self, index, role=Qt.DisplayRole):
row = index.row()
if role == PersonModel.NAME_ROLE:
return self.persons[row]["name"]
if role == PersonModel.AGE_ROLE:
return self.persons[row]["age"]
def rowCount(self, parent=QModelIndex()):
return len(self.persons)
def roleNames(self):
return {
PersonModel.NAME_ROLE: b'name',
PersonModel.AGE_ROLE: b'age'
}
def updateIndex(self, int):
self.currentIndex = int
print("updating index from click", self.currentIndex)
def addPerson(self, name, age):
self.beginInsertRows(QModelIndex(), self.rowCount(), self.rowCount())
self.persons.append({'name': name, 'age': age})
self.endInsertRows()
def insertPerson(self, row, name, age):
self.beginInsertRows(QModelIndex(), row, row)
self.persons.insert(row, {'name': name, 'age': age})
self.endInsertRows()
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())
def deletePerson(self, row):
self.beginRemoveColumns(QModelIndex(), row, row)
del self.persons[row]
self.endRemoveRows()
why does the list of persons return undefined in qml?
In case anyone is wondering, i am trying to create a model class that i can instantiate with by passing any list of dictionaries and use this list as the model
property in different ListView
elements. In this model class i have add
, insert
, edit
, delete
that i can use consistently throughout all instances and thus avoid repetitions.
Also, i am trying to separate the model from the view such that the data flow is one way ie qml
informs python of any user interaction and all changes in the model
will be handled on python which qml will change accordingly whenever model
changes.
model
property in differentListView
in qml – eugeneoei