Почему layoutChanged.emit() не обновляет QListView при использовании QSortFilterProxyModel?

У меня возникли проблемы с тем, чтобы QListView работал с прокси-моделями.

Я начал использовать QListViews с моделями без каких-либо проблем и изменил данные во время выполнения, используя сигналы datachanged.emit() этой модели.

Однако, когда я пытаюсь изменить данные в QListView на основе прокси-модели, эти данные не обновляются в интерфейсе.

Я свел это к минимальному примеру, но до сих пор не вижу основной причины такого поведения:

from PyQt5.QtWidgets import (QWidget, QHBoxLayout, QApplication, QListView)
from PyQt5 import QtCore


# model for QListView
class ListModel(QtCore.QAbstractListModel):
    def __init__(self, items):
        super().__init__()
        self.items = items

    def data(self, index, role):
        if role == QtCore.Qt.DisplayRole:
            return self.items[index.row()]

    def rowCount(self, index):
        return len(self.items)


class MainWindow(QWidget):
    def __init__(self):
        super().__init__()
        # creating list with "standard" model and an initial dataset => this works
        list_view_1 = QListView()
        list_view_1.setModel(ListModel(['original', 'model']))

        # creating list with proxy based on source model and an initial dataset => this works
        list_view_2 = QListView()
        proxy = QtCore.QSortFilterProxyModel()
        proxy.setSourceModel(ListModel(['original', 'proxy+model']))
        list_view_2.setModel(proxy)

        # changing data in model and emitting layout change => this works
        list_view_1.model().items = ['changed', 'model']
        list_view_1.model().layoutChanged.emit()

        # changing data in proxy and emitting layout change => this does not work?
        list_view_2.model().items = ['changed', 'proxy+model']
        list_view_2.model().layoutChanged.emit()

        # adding layout to the interface
        hbox = QHBoxLayout()
        hbox.addWidget(list_view_1)
        hbox.addWidget(list_view_2)

        self.setLayout(hbox)
        self.show()


app = QApplication([])
window = MainWindow()
app.exec_()

Ни один из моих поисков не привел к объяснению этого поведения, связанный поток стека только упомянул порядок моделей, который я уже реализовал таким образом.

Может ли кто-нибудь указать мне решение о том, как правильно обновлять данные в прокси-модели?


person Christian Karcher    schedule 26.06.2020    source источник


Ответы (1)


Проблема в том, что вы создаете атрибут (элементы) в прокси-модели вместо обновления элементов исходной модели, решение заключается в обновлении элементов исходной модели:

# ...
# changing data in model and emitting layout change => this works
list_view_1.model().items = ["changed", "model"]
list_view_1.model().layoutChanged.emit()

# changing data in proxy and emitting layout change => this does not work?
list_view_2.model().sourceModel().items = ["changed", "proxy+model"]
list_view_2.model().layoutChanged.emit()
# ...
person eyllanesc    schedule 26.06.2020
comment
Спасибо! Я не знал о фоновой исходной модели, я думал, что модель () будет какой-то объединенной версией обоих. Я прямо наткнулся на следующую проблему при попытке добавить элементы с использованием этого подхода, и добавленный элемент снова не отображается. Но причина была та же, вместо вызова model().layoutChanged (который обновляет существующие записи в моем минимальном примере, но не добавляет никаких дополнительных) мне нужно было вызвать model().sourceModel().layoutChanged, который кажется, обновляет список на более глубоком уровне. - person Christian Karcher; 26.06.2020