发出 dataChanged 信号 PyQt5

Posted

技术标签:

【中文标题】发出 dataChanged 信号 PyQt5【英文标题】:emit dataChanged signal PyQt5 【发布时间】:2017-08-20 12:45:29 【问题描述】:

我无法从我的模型中发出 dataChanged 信号。我在python 3.5.2、PyQt5.9.1下。

我尝试了至少 4 种不同的语法,但这些都不适合我:这个模型的不同视图只有在我点击它们时才会更新...

@pyqtSlot()
def setData(self, index: QModelIndex, Any, role=None):
    if role == QtCore.Qt.EditRole:
        row = index.row()
        color = QtGui.QColor(Any)
        if color.isValid():
            self._datas[row] = color
            # self.dataChanged.emit(index,index) # doesn't work because PyQt5 changed signature
            # self.dataChanged.emit(index, index, []) # doesn't update other views of the same model
            # self.dataChanged.emit(index,index,[QtCore.Qt.EditRole,]) # neither
            # self.data_changed.emit(index,index) # class method is 'data_changed = pyqtSignal(QModelIndex,QModelIndex)', doesn't work 
            return True
    return False

这个问题How to emit dataChanged in PyQt5 被标记为已解决,但是我无法重现

编辑: 一个可验证的示例,具有同一模型的多个视图。每当我更改颜色时,我都希望所有视图都会更新

EDIT_2 已解决...只是一个错字...此示例按预期工作

from PyQt5 import QtGui, QtCore
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import QApplication
from PyQt5.QtCore import QModelIndex, pyqtSignal,QAbstractListModel, pyqtSlot
import sys


class listModel(QAbstractListModel):

    def __init__(self, colors=None):
        super(QAbstractListModel, self).__init__()
        self._datas = colors


    def data(self, index: QModelIndex, role=None):
        row = index.row()
        value = self._datas[row]

        if role == QtCore.Qt.DisplayRole:
            return value.name()

        elif role == QtCore.Qt.DecorationRole:
            pixmap = QtGui.QPixmap(12,12)
            pixmap.fill(value)
            icon = QtGui.QPixmap(pixmap)
            return icon

        elif role == QtCore.Qt.ToolTipRole:
            return "Hex code: " + self._datas[row].name()


    def rowCount(self, parent=None, *args, **kwargs):
        return len(self._datas)

    def headerData(self, p_int, Qt_Orientation, role=None):
         if role == QtCore.Qt.DisplayRole:
             if Qt_Orientation == QtCore.Qt.Horizontal:
                 return "Palette"
             else:
                return "Color a".format(a=p_int)

    def flags(self, QModelIndex: QModelIndex):
        # check state editable or not?
        return QtCore.Qt.ItemIsEditable | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled

    @pyqtSlot()
    def setData(self, QModelIndex, Any, role=None):

        if role == QtCore.Qt.EditRole:
            row = QModelIndex.row()
            color = QtGui.QColor(Any)
            if color.isValid():
                self._datas[row] = color
                self.dataChanged.emit(QModelIndex, QModelIndex, [])
                return True
        return False

if __name__ == '__main__':
    app = QApplication(sys.argv)
    red = QtGui.QColor(255,0,0)
    green = QtGui.QColor(0, 255, 0)
    blue = QtGui.QColor(0, 0, 255)
    colors = [red,green,blue]

    model = listModel(colors)

    listView = QtWidgets.QListView()
    listView.setModel(model)
    listView.setWindowTitle('list')
    listView.show()

    treeV = QtWidgets.QTreeView()
    treeV.setModel(model)
    treeV.setWindowTitle('tree')
    treeV.show()

    tableV = QtWidgets.QTableView()
    tableV.setModel(model)
    tableV.setWindowTitle('table')
    tableV.show()


    sys.exit(app.exec_())

【问题讨论】:

第二种和第三种形式是唯一正确的两种。您显然能够发出信号 - 真正的问题是视图的更新,这可能完全是由其他原因引起的。如需帮助,您应该提供minimal reproducible example。 添加了可验证的示例 在 linux 上使用 python 3.6.2、qt 5.9.1 和 pyqt 5.9 时,您的示例按预期工作。也就是说,如果我在任何窗口中编辑任何颜色,所有其他视图都会立即更新。 ...我犯了一个愚蠢的错误。刚刚再次启动它,它的工作原理。 【参考方案1】:

self.dataChanged.emit(index, index, [QtCore.Qt.EditRole]) 是正确的。您的代码中的其他地方一定有错误。

【讨论】:

以上是关于发出 dataChanged 信号 PyQt5的主要内容,如果未能解决你的问题,请参考以下文章

PyQT 列表视图没有响应 datachanged 信号

Qt dataChanged信号较慢然后隐藏/显示视图

Qt - 仅在发出两个信号时才调用插槽

如何处理圆图的Datachange信号?

无法在 QAbstractItemModel 的 dataChanged 信号槽中获取发送者对象

dataChanged 信号不适用于 ComboBoxDelegate