You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 15:48:30