Синхронизация QAbstractListModel с QML

#python #pyqt #qml

Вопрос:

У меня есть простой класс StudentListModel, который реализует QAbstractListModel.

 class StudentListModel(QAbstractListModel):  NAME = Qt.UserRole   1  AGE = Qt.UserRole   2   def __init__(self, students):  super().__init__()  self.students = students   def roleNames(self):  return {  StudentListModel.NAME: b'name',  StudentListModel.AGE: b'age',  }   def rowCount(self, parent=None, *args, **kwargs):  return len(self.students)   def data(self, QModelIndex, role=None):  row = self.students[QModelIndex.row()]   if role == StudentListModel.NAME:  return row["name"]  elif role == StudentListModel.AGE:  return row["age"]   return None   def remove(self, index):  self.students.pop(index)  

Модель StudentListModel передается в файл QML. В QML будут отображаться записи моделей.

 import QtQuick 2.15 import QtQuick.Controls 2.15  Rectangle {  id: container   signal remove(int index)   Column {  spacing: 15   Repeater {  model: studentListModel   Row {  spacing: 10   Text {  text: model.name  }   Button {  text: "Remove"  onClicked: container.remove(index)  }  }  }  } }  

Код, который соединяет QML с моделью StudentList, представлен здесь:

 def main():  students = [  {"name": "Vitaliy ", "age": "21"},  {"name": "Eugene", "age": "26"},  {"name": "Tommy", "age": "26"}  ]   model = StudentListModel(students)   app = QApplication(sys.argv)  widget = QQuickWidget()   widget.setSource(QUrl('stack.qml'))  widget.rootContext().setContextProperty('studentListModel', model)  widget.rootObject().remove.connect(lambda index: model.remove(index))   widget.setGeometry(0, 0, 320, 800)  widget.show()   return app.exec_()   if __name__ == '__main__':  sys.exit(main())  

And here is the screenshot of the app in action:

введите описание изображения здесь

Нет никаких проблем с отображением записей модели в QML. Проблема в том, когда я хочу удалить запись. Когда я нажимаю удалить, QML получает индекс выбранной записи и отправляет сигнал. Блок main() будет обрабатывать излучение сигнала с помощью лямбда-функции. Лямбда-функция получит индекс и вызовет метод remove из модели, передав полученный индекс. После этого модель удалит запись, однако QML не отображает обновленную модель. Есть ли способ синхронизировать модель с QML, чтобы при удалении записи она также удалялась в QML ?

Ответ №1:

Вы должны вызвать методы beginRemoveRows и endRemoveRows до и после удаления соответственно:

 class StudentListModel(QAbstractListModel):  NAME = Qt.UserRole   1  AGE = Qt.UserRole   2   def __init__(self, students):  super().__init__()  self.students = students   def roleNames(self):  return {  StudentListModel.NAME: b"name",  StudentListModel.AGE: b"age",  }   def rowCount(self, parent=QModelIndex()):  return len(self.students)   def data(self, index, role=Qt.DisplayRole):  row = self.students[index.row()]   if role == StudentListModel.NAME:  return row["name"]  elif role == StudentListModel.AGE:  return row["age"]   def remove(self, index):  self.beginRemoveRows(QModelIndex(), index, index)  self.students.pop(index)  self.endRemoveRows()  

Комментарии:

1. Работает идеально ! Спасибо!