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

如何将PyQt4的QAbstractItemModel对象转换为QStandardItemModel对象

嘿,这个问题我之前折腾PyQt的时候也碰到过!确实QStandardItemModel没有直接接收另一个QAbstractItemModel实例的构造函数,不过我们可以通过遍历源模型的索引来手动复制数据,下面给你两种靠谱的实现方式:

方法一:递归遍历复制(支持树形/层级结构)

如果你的源模型是带层级的树形结构(比如QTreeView用的模型),这个方法能完整保留原模型的结构和所有数据:

def copy_model_to_standard(source_model: QtGui.QAbstractItemModel) -> QtGui.QStandardItemModel:
    target_model = QtGui.QStandardItemModel()
    
    def copy_item(source_index, parent_item):
        # 创建新的标准项
        item = QtGui.QStandardItem()
        # 复制所有需要的角色数据(不止默认的显示文本)
        # 可以根据需求添加更多角色,比如Qt.DecorationRole、Qt.ToolTipRole等
        for role in [QtCore.Qt.DisplayRole, QtCore.Qt.EditRole, QtCore.Qt.TextAlignmentRole]:
            data = source_model.data(source_index, role)
            if data is not None:
                item.setData(data, role)
        # 将当前项添加到父项中
        parent_item.appendRow(item)
        # 递归处理所有子项
        row_count = source_model.rowCount(source_index)
        col_count = source_model.columnCount(source_index)
        for row in range(row_count):
            for col in range(col_count):
                child_index = source_model.index(row, col, source_index)
                if child_index.isValid():
                    copy_item(child_index, item)
    
    # 遍历根级所有行列
    root_row_count = source_model.rowCount()
    root_col_count = source_model.columnCount()
    for row in range(root_row_count):
        for col in range(root_col_count):
            root_index = source_model.index(row, col)
            if root_index.isValid():
                copy_item(root_index, target_model.invisibleRootItem())
    
    return target_model

这个方法会逐个遍历每个有效索引,复制指定角色的所有数据,同时递归处理子项,完美还原原模型的层级结构。

方法二:快速复制(仅适用于平面表格模型)

如果你的源模型是简单的平面表格(比如QTableView用的模型,没有子项层级),可以用更高效的简化版实现:

def copy_table_model(source_model: QtGui.QAbstractItemModel) -> QtGui.QStandardItemModel:
    target_model = QtGui.QStandardItemModel()
    # 先同步行列数
    target_model.setRowCount(source_model.rowCount())
    target_model.setColumnCount(source_model.columnCount())
    
    # 复制水平表头
    for col in range(source_model.columnCount()):
        header_text = source_model.headerData(col, QtCore.Qt.Horizontal, QtCore.Qt.DisplayRole)
        target_model.setHorizontalHeaderItem(col, QtGui.QStandardItem(header_text))
    # 复制垂直表头(如果需要的话)
    for row in range(source_model.rowCount()):
        header_text = source_model.headerData(row, QtCore.Qt.Vertical, QtCore.Qt.DisplayRole)
        target_model.setVerticalHeaderItem(row, QtGui.QStandardItem(header_text))
    
    # 逐个单元格复制数据
    for row in range(source_model.rowCount()):
        for col in range(source_model.columnCount()):
            source_index = source_model.index(row, col)
            item = QtGui.QStandardItem(source_model.data(source_index))
            # 可选:复制文本对齐等额外属性
            alignment = source_model.data(source_index, QtCore.Qt.TextAlignmentRole)
            if alignment is not None:
                item.setTextAlignment(alignment)
            target_model.setItem(row, col, item)
    
    return target_model

这个方法跳过了递归逻辑,直接按行列批量处理,速度更快,但只适合没有层级的平面模型。

几个注意点

  • 一定要根据源模型的结构选对方法:树形结构用递归,平面表格用快速复制,否则会丢失子项数据。
  • 不要只复制DisplayRole的数据,记得把你需要的其他角色(比如编辑角色、提示角色、图标角色等)都加进遍历列表里,不然新模型会缺失这些属性。
  • 如果源模型有自定义角色,也要把对应的角色ID加入到遍历的role列表中,确保所有数据都被复制。

内容的提问来源于stack exchange,提问作者Felipe Ruiz Reyes

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:19:18