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

如何定制QTableView列以展示与模型不同的内容?

解决方案:扩展现有PandasModel实现只读计算列

你不需要额外创建模型,也不用修改QTableView,直接在现有的PandasModel里扩展逻辑,就能动态生成只读的额外列,同时完全保留原DataFrame(Table1)的结构。

具体实现思路

核心是重写QAbstractTableModel的几个关键方法,让模型在返回数据时动态计算出绝对路径、文件大小这类临时数据,完全不用修改原DataFrame的存储内容:

  1. 调整列数统计,把新增的列算进去
  2. 为新增列设置表头文本
  3. 针对新增列动态计算并返回对应数据
  4. 标记新增列为只读,禁止编辑操作

完整代码示例

from PySide6.QtCore import QAbstractTableModel, Qt, QModelIndex
import pandas as pd
import os

class PandasModel(QAbstractTableModel):
    """A model to interface a Qt view with pandas dataframe """

    def __init__(self, dataframe: pd.DataFrame, root_path: str, parent=None):
        QAbstractTableModel.__init__(self, parent)
        self._dataframe = dataframe
        self._root_path = root_path  # 文件所在根目录,根据实际场景传入

    def rowCount(self, parent=QModelIndex()):
        return self._dataframe.shape[0]

    def columnCount(self, parent=QModelIndex()):
        # 原列数 + 新增的2列(绝对路径、文件大小)
        return self._dataframe.shape[1] + 2

    def headerData(self, section, orientation, role=Qt.DisplayRole):
        if role == Qt.DisplayRole and orientation == Qt.Horizontal:
            if section < self._dataframe.shape[1]:
                return self._dataframe.columns[section]
            elif section == self._dataframe.shape[1]:
                return "abs path"
            elif section == self._dataframe.shape[1] + 1:
                return "size"
        return super().headerData(section, orientation, role)

    def data(self, index, role=Qt.DisplayRole):
        if not index.isValid():
            return None
        
        row = index.row()
        col = index.column()

        if role == Qt.DisplayRole:
            # 返回原DataFrame的列数据
            if col < self._dataframe.shape[1]:
                return str(self._dataframe.iloc[row, col])
            # 计算并返回绝对路径
            elif col == self._dataframe.shape[1]:
                filename = self._dataframe.iloc[row, 0]
                return os.path.abspath(os.path.join(self._root_path, filename))
            # 计算并返回文件大小(转换为KB)
            elif col == self._dataframe.shape[1] + 1:
                filename = self._dataframe.iloc[row, 0]
                file_path = os.path.join(self._root_path, filename)
                if os.path.exists(file_path):
                    size_kb = os.path.getsize(file_path) / 1024
                    return f"{round(size_kb, 2)}KB"
                else:
                    return "文件不存在"
        
        return None

    def flags(self, index):
        # 新增列设置为只读
        if index.column() >= self._dataframe.shape[1]:
            return Qt.ItemIsSelectable | Qt.ItemIsEnabled
        # 原列保持默认规则(如果需要原列也只读,直接返回上面的flags即可)
        return super().flags(index)

为什么不选其他方案?

  • 不用定制QTableView:Qt的MVC架构中,视图只负责展示数据,把计算逻辑塞进视图会导致代码耦合度高,后续修改或扩展非常麻烦。
  • 不用创建两个模型:双模型会带来数据同步问题——原DataFrame更新时,你需要手动同步第二个模型,容易出现数据不一致的情况,完全没必要。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 09:25:21