PyQT列表视图未响应数据更改信号

5 投票
2 回答
8738 浏览
提问于 2025-04-17 23:17

我一直在跟着一些教程,想要设置一个列表模型。我的主窗口有两个列表视图,它们都在使用同一个模型。当我在一个列表中更新某个项目时,另一个列表不会自动更新,直到我点击它,这时它才会更新。所以看起来是数据变化的信号没有被发出,但我搞不清楚我的代码和我参考的例子有什么不同。

main.py

class Main(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(Main, self).__init__(parent)
        self.ui = uic.loadUi("mainwindow.ui", self)

        # Test model and listviews
        data = [10,20,30,40,50]
        myModel = model.MyListModel(data)
        self.ui.listView.setModel(myModel)
        self.ui.listView_2.setModel(myModel)

model.py

class MyListModel(QtCore.QAbstractListModel):
    def __init__(self, data=[], parent=None):
        super(MyListModel, self).__init__(parent)
        self.__data = data

    def rowCount(self, parent=QtCore.QModelIndex()):
        return len(self.__data)

    def data(self, index, role=QtCore.Qt.DisplayRole):
        row = index.row()
        if role in (QtCore.Qt.DisplayRole, QtCore.Qt.EditRole):
            return str(self.__data[row])

        if role == QtCore.Qt.ToolTipRole:
            return 'Item at {0}'.format(row)

    def flags(self, index):
        return QtCore.Qt.ItemIsEditable | QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable

    def setData(self, index, value, role=QtCore.Qt.EditRole):
        if role == QtCore.Qt.EditRole:
            self.__data[index.row()] = value
            self.dataChanged.emit(index, index)
            return True
        return False

有没有人能看出这里有什么问题?顺便说一下,我使用的是PyQT5.2.1和Python 3.3。

2 个回答

2

解决方案:

self.dataChanged.emit(index, index, ())

对我来说不管用(python 2.7,PyQt5)。
但下面的其中一个会有效:

self.dataChanged.emit(index, index, [])


self.dataChanged.emit(index, index, list())
8

问题出在 dataChanged 信号的定义上。在 Qt4 中,它的写法是这样的:

    dataChanged(const QModelIndex & topLeft, const QModelIndex & bottomRight)

但是在 Qt5 中,它的写法变成了这样:

    dataChanged(const QModelIndex & topLeft, const QModelIndex & bottomRight,
                const QVector<int> & roles = QVector<int>())

当我用 PyQt-5.1.1 试你的示例代码时,发现如果不传第三个参数就会报错。严格来说,这种情况是不对的,因为第三个参数是有默认值的。所以这可能就是行为变化的原因。

现在看来,为了让 PyQt5 正常工作,你必须明确地传递一个空列表作为 dataChanged 的第三个参数:

    self.dataChanged.emit(index, index, [])

或者,当然,你也可以传递一个实际发生变化的角色列表:

    self.dataChanged.emit(index, index, [QtCore.Qt.EditRole])

撰写回答