我有一个QListView & QIdentityProxyModel的测试代码。
当我实现QIdentityProxyModel时,错误发生在setData,dataChanged.If的函数--我没有实现它,错误没有发生。
我试图通过PyQt6做同样的事情,但结果是一样的。
我试着用命令提示符来做,没有错误提示。
相反,我可以成功地在QTreeView、QTableView上实现QTreeView,没有问题,我一直认为QListView是这些查看器中最简单的。
我的代码中的问题在哪里?
from PySide6 import QtWidgets, QtGui, QtCore
import sys
class ListView(QtWidgets.QListView):
def __init__(self, parent=None):
super(ListView, self).__init__(parent)
def insertItem(self):
self.model().insertRows(0, 1)
self.model().setData(self.model().index(0, 0), ListItem(text="Hallo!"))
class ListItem(object):
def __init__(self, text="", parent=None):
super(ListItem, self).__init__()
self.data = []
self.text = "Hi!" if not text else text
class ListModel(QtCore.QAbstractListModel):
def __init__(self, parent=None):
super(ListModel, self).__init__(parent)
self.items = []
def columnCount(self, parent=QtCore.QModelIndex()):
return 1
def rowCount(self, parent=QtCore.QModelIndex()):
return len(self.items)
def headerData(self, index):
return "LIST"
def index(self, row, column, _parent=QtCore.QModelIndex()):
if row >= len(self.items) - 1:
return QtCore.QModelIndex()
if self.items:
childIndex = self.createIndex(row, column, self.items[row])
return childIndex
return QtCore.QModelIndex()
def data(self, index, role=QtCore.Qt.ItemDataRole.DisplayRole):
if not index.isValid():
return None
row = index.row()
column = index.column()
if role == QtCore.Qt.DisplayRole:
if 0 <= row < self.rowCount() and 0 <= column < self.columnCount():
return self.items[row].text
def setData(self, index, value, role=QtCore.Qt.ItemDataRole.EditRole):
if role == QtCore.Qt.ItemDataRole.EditRole:
row = index.row()
if 0 <= row < self.rowCount():
self.items[row] = value
self.dataChanged["QModelIndex", "QModelIndex"].emit(index, index)
return True
return False
def flags(self, index):
return QtCore.Qt.ItemFlag.ItemIsEnabled|QtCore.Qt.ItemFlag.ItemIsSelectable
def index(self, row, column, parent=QtCore.QModelIndex()):
if row > len(self.items) - 1:
return QtCore.QModelIndex()
elif self.items:
childIndex = self.createIndex(row, column, self.items[row])
return childIndex
return QtCore.QModelIndex()
def insertRows(self, position, rows=1, parent=QtCore.QModelIndex()):
self.beginResetModel()
self.beginInsertRows(parent, position, position+rows-1)
for i in range(rows):
self.items.insert(position+i, ListItem())
self.endInsertRows()
self.dataChanged["QModelIndex", "QModelIndex"].emit(parent, parent)
self.layoutChanged.emit()
self.endResetModel()
return True
class ListIdentityModel(QtCore.QIdentityProxyModel):
def __init__(self, parent=None):
super(ListIdentityModel, self).__init__(parent)
def mapFromSource(self, sourceIndex):
if not sourceIndex.isValid():
return QtCore.QModelIndex()
return self.createIndex(sourceIndex.row(), sourceIndex.column(), sourceIndex.internalPointer())
def mapSelectionFromSource(self, selection):
sourceIndexes = selection.indexes()
proxySelection = QtCore.QItemSelection(sourceIndexes[0], sourceIndexes[-1])
return proxySelection
def mapSelectionToSource(self, selection):
proxyIndexes = selection.indexes()
sourceSelection = QtCore.QItemSelection(proxyIndexes[0], proxyIndexes[-1])
return sourceSelection
def mapToSource(self, proxyIndex):
if not proxyIndex.isValid():
return QtCore.QModelIndex()
return self.sourceModel().createIndex(proxyIndex.row(), proxyIndex.column(), proxyIndex.internalPointer())
def setSourceModel(self, sourceModel):
self.beginResetModel()
super(ListIdentityModel, self).setSourceModel(sourceModel)
self.endResetModel()
def main():
app = QtWidgets.QApplication([]) if QtWidgets.QApplication.instance() is None else QtWidgets.QApplication.instance()
widget = QtWidgets.QWidget()
pushbutton = QtWidgets.QPushButton("insert item")
main_view = ListView()
model = ListModel(main_view)
main_view.setModel(model)
#comment or uncomment
identity_view = ListView()
identityModel = ListIdentityModel()
identity_view.setModel(identityModel)
identityModel.setSourceModel(model)
#
hboxlayout = QtWidgets.QHBoxLayout()
hboxlayout.addWidget(pushbutton)
hboxlayout.addWidget(main_view)
#
hboxlayout.addWidget(identity_view)
#
widget.setLayout(hboxlayout)
pushbutton.clicked.connect(main_view.insertItem)
widget.show()
sys.exit(app.exec())
if __name__ == "__main__":
main()发布于 2022-03-01 18:37:22
insertRows()函数不应该使用beginResetModel() (顾名思义,它开始了模型reset),也不应该使用layoutChanged():不仅应该始终在layoutAboutToBeChanged()后面调用它,而且只有在对模型进行排序时才应该使用该特性。
发出dataChanged()也是没有意义的,因为插入的行将导致视图对新索引调用data()。
def insertRows(self, position, rows=1, parent=QtCore.QModelIndex()):
self.beginInsertRows(parent, position, position+rows-1)
for i in range(rows):
self.items.insert(position+i, ListItem())
self.endInsertRows()
return True还要注意的是,您定义了两次index(),但是只有第二次使用并且实际上是正确的,这是因为if row > len(self.items) - 1:检查与前面的>=相反,这是错误的。在任何情况下,如果您使用的是QAbstractListItem,这是一个单维模型,那么绝对没有必要覆盖index(),您可以使用默认的实现。
https://stackoverflow.com/questions/71302836
复制相似问题