为什么 layoutChanged.emit() 在使用 QSortFilterProxyModel 时不更新 QListView?

Why does layoutChanged.emit() not update the QListView when using a 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_()

None 我的搜索导致了对这种行为的解释,a related stack thread 只提到了模型的顺序,我已经用这种方式实现了。

谁能告诉我如何正确更新“代理模型”中的数据的解决方案?

问题是您在代理模型中创建属性(项目)而不是更新源模型项目,解决方案是更新源模型项目:

# ...
# 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().<b>sourceModel()</b>.items = ["changed", "proxy+model"]
list_view_2.model().layoutChanged.emit()
# ...