使用Qt代理模型实现虚拟行分组时的选中异常问题
问题
- 尝试通过Qt代理模型添加虚拟行,对源模型中的项进行分组,目前功能初步实现,但被重父到虚拟行的“A”项无法被选中,“B”和“C”项可正常选中
- 以下是用于原型验证的测试代码,经过多周资料查询及尝试后编写,仍未定位到问题根源
- 不确定当前实现思路是否正确,希望能获得更优方案;曾找到一些C++的分组代理模型示例,但过于复杂难以理解
#!/usr/bin/env python from Qt import QtCore, QtGui, QtWidgets class VirtualRowProxyModel(QtCore.QSortFilterProxyModel): # Some internal id indicating when its a virtual row IS_VIRTUAL = 5 def __init__(self, parent=None): super(VirtualRowProxyModel, self).__init__(parent) def flags(self, index): return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable def mapToSource(self, proxyIndex): if self._isVirtualRow(proxyIndex): return QtCore.QModelIndex() return super(VirtualRowProxyModel, self).mapToSource(proxyIndex) def mapFromSource(self, sourceIndex): row = sourceIndex.row() column = sourceIndex.column() parent = sourceIndex.parent() if row == 0 and not parent.isValid(): return self.index(0, 0).child(row, column) return super(VirtualRowProxyModel, self).mapFromSource(sourceIndex) def hasChildren(self, parent=QtCore.QModelIndex()): if self._isVirtualRow(parent): return True return super(VirtualRowProxyModel, self).hasChildren(parent) def index(self, row, column, parent=QtCore.QModelIndex()): if not parent.isValid(): return self.createIndex(row, column, self.IS_VIRTUAL) return super(VirtualRowProxyModel, self).index(row, column, parent) def parent(self, index): if not index.isValid(): return QtCore.QModelIndex() if self._isVirtualRow(index): return QtCore.QModelIndex() sourceIndex = self.mapToSource(index) if not sourceIndex.parent().isValid(): return self.index(0, 0) return super(VirtualRowProxyModel, self).parent(index) def data(self, proxyIndex, role=QtCore.Qt.DisplayRole): # if role == QtCore.Qt.DisplayRole: # sourceIndex = self.mapToSource(proxyIndex) # return str([sourceIndex.row(), sourceIndex.data(), # proxyIndex.isValid(), proxyIndex.parent().isValid(), sourceIndex.parent().isValid()]) if self._isVirtualRow(proxyIndex): if role == QtCore.Qt.DisplayRole: sourceIndex = self.mapToSource(proxyIndex) return "-VIRTUAL ROW-" if role == QtCore.Qt.UserRole: return True return None return super(VirtualRowProxyModel, self).data(proxyIndex, role) def rowCount(self, parent=QtCore.QModelIndex()): if not parent.isValid(): return 3 if self._isVirtualRow(parent): if parent.row() == 0: return 1 return 0 return self.sourceModel().rowCount(self.mapToSource(parent)) def _isVirtualRow(self, index): return index.isValid() and index.internalId() == self.IS_VIRTUAL def itemRow(name): return [QtGui.QStandardItem(name)] class Ctrl(QtCore.QObject): def __init__(self, parent=None): super(Ctrl, self).__init__(parent) self.window = QtWidgets.QFrame() layout = QtWidgets.QHBoxLayout(self.window) self.view = QtWidgets.QTreeView() self.view.setAlternatingRowColors(True) model = QtGui.QStandardItemModel() row1 = itemRow("A") model.appendRow(row1) row2 = itemRow("B") row1[0].appendRow(row2) row3 = itemRow("C") row2[0].appendRow(row3) self.proxy = VirtualRowProxyModel() self.proxy.setSourceModel(model) self.view.setModel(self.proxy) self.view.expandAll() layout.addWidget(self.view) if __name__ == '__main__': app = QtWidgets.QApplication([]) app.setStyle("fusion") ctrl = Ctrl() window = ctrl.window window.resize(600, 300) window.show() window.raise_() app.exec_()
内容的提问来源于stack exchange,提问作者JaredR
相关产品推荐
相关产品推荐

