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

如何正确实现QSortFilterProxyModel的parent()方法处理虚拟列?

问题根源

  • 触发访问冲突的核心原因有两个:
    1. QSortFilterProxyModel内部会对所有有效索引做源映射校验,你自定义的第4列索引mapToSource返回空,但如果又给它设置了有效父索引,内部树结构遍历的时候会出现逻辑异常,直接触发内存访问错误。
    2. 用字典存储QModelIndex作为缓存的方式也不可靠:Qt的QModelIndex是生命周期极短的临时对象,PySide的Python包装对象很容易被GC提前回收,后续访问字典里存的实际是悬垂引用,自然会崩溃。

正确实现方案

你完全不需要修改parent()方法的逻辑,也不需要自行维护索引的父子关系,直接通过源模型映射取数即可,逻辑更简单也不会崩溃:

from PySide2 import QtCore, QtWidgets


class MyProxyModel(QtCore.QSortFilterProxyModel):
    def columnCount(self, index):
        # 源模型列数基础上加1作为自定义列,适配不同场景下的源模型列数变化
        return super().columnCount(index) + 1

    def mapToSource(self, index):
        if index.column() == 4:
            # 自定义列映射到第0列的源索引,避免返回空索引导致内部校验错误
            return super().mapToSource(self.index(index.row(), 0, index.parent()))
        return super().mapToSource(index)

    def data(self, index, role=QtCore.Qt.DisplayRole):
        if index.column() == 4:
            # 直接复用第0列对应的数据,不需要自行维护索引关系
            return super().data(self.index(index.row(), 0, index.parent()), role)
        return super().data(index, role)

    def headerData(self, section, orientation, role=QtCore.Qt.DisplayRole):
        if section == 4 and orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole:
            return 'My Column'
        return super().headerData(section, orientation, role)


if __name__ == '__main__':
    app = QtWidgets.QApplication([])
    dialog = QtWidgets.QFileDialog()
    dialog.setOption(dialog.DontUseNativeDialog, True)
    dialog.setProxyModel(MyProxyModel(dialog))
    dialog.exec_()

该实现完全复用父类的索引逻辑,不需要自定义index()、parent()方法,也不需要额外的字典缓存,避免了自定义索引树带来的校验错误和悬垂引用问题,运行不会崩溃,可正常实现新增列展示第一列内容的需求。


内容的提问来源于stack exchange,提问作者Unai

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 00:00:01