PyQT列表视图不响应datachanged信号

时间:2014-03-21 13:35:18

标签: python qt pyqt pyqt5 qabstractlistmodel

我一直在关注一些教程并尝试设置列表模型。我的主窗口有两个访问相同模型的列表视图。当我更新一个列表中的项目时,另一个列表不会更新自己,直到它获得焦点(我点击它)。因此看起来似乎没有发出dataChanged信号,但是我无法弄清楚我的代码与我所基于的任何示例的不同之处。

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 个答案:

答案 0 :(得分: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尝试你的示例代码时,在尝试发出没有第三个参数的信号时出现错误。严格来说,这是不正确的行为,因为第三个参数有一个默认值。所以这也许是行为发生变化的原因。

但似乎你现在必须显式地发出一个空列表作为dataChanged的第三个参数,以便在PyQt5中正常工作:

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

或者,当然,会发出实际已更改的角色列表:

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

答案 1 :(得分:2)

解决方案:

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

对我不起作用(python 2.7,PyQt5)。
但下列之一将起作用:

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


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