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

PySide6/QTableView更新失败:index方法调用触发TypeError

解决QAbstractTableModel调用index时的TypeError及相关问题

核心错误原因

你触发的TypeError,是因为直接调用了PandasModel类的index方法,而index是QAbstractTableModel实例的方法,必须通过模型对象来调用,不能用类本身。同时你的代码还有几个其他问题导致功能无法正常工作:

具体修复步骤

  1. 保存模型实例的引用
    在MainWidget中,你创建了MyTable但没有保存它的模型实例,而且self.pandasModel赋值的是类而非实例。需要修改MainWidget的初始化代码,保存MyTable的引用,后续通过它获取模型实例。

  2. 正确创建QModelIndex对象
    要获取表格的索引,需要调用模型实例的index()方法,而不是类的。

  3. 修复DataFrame赋值方式
    setData中用self._data[row][column] = value会触发Pandas的链式索引警告,应该改用iloc进行位置赋值。

  4. 修正未定义的变量
    __handleSpinBox里的result是未定义的,应该用信号传来的value参数。

修复后的完整代码

from PySide6.QtCore import *
from PySide6.QtWidgets import QWidget, QHBoxLayout, QTableView, QApplication, QSpinBox
from PySide6.QtGui import *
import sys
import pandas as pd


class PandasModel(QAbstractTableModel):
    def __init__(self, table):
        super(PandasModel, self).__init__()
        self._data = pd.DataFrame(table)

    def rowCount(self, parent=None):
        return self._data.shape[0]

    def columnCount(self, parent=None):
        return self._data.shape[1]

    def data(self, index, role=Qt.DisplayRole):
        if not index.isValid():
            return None
        if role == Qt.DisplayRole or role == Qt.EditRole:
            return str(self._data.iloc[index.row(), index.column()])
        return None

    def setData(self, index, value, role=Qt.EditRole):
        if not index.isValid():
            return False
        if role == Qt.EditRole:
            row = index.row()
            column = index.column()
            # 改用iloc避免链式索引问题
            self._data.iloc[row, column] = value
            # 正确触发dataChanged信号,需要传递左上角和右下角索引(单个单元格传同一个)
            self.dataChanged.emit(index, index)
            return True
        return False

    def headerData(self, col, orientation, role):
        if orientation == Qt.Horizontal and role == Qt.DisplayRole:
            return self._data.columns[col]
        return None


class MyTable(QTableView):
    def __init__(self, model: QAbstractTableModel, data, parent=None):
        super().__init__(parent)
        self.data = data
        self.horizontalHeader().setVisible(True)
        self.verticalHeader().setVisible(False)
        self.model = model(pd.DataFrame(data, columns=['Col1', 'Col2', 'Col3']))
        self.setModel(self.model)


class MainWidget(QWidget):
    def __init__(self):
        super().__init__()
        self.spinBox = QSpinBox()
        self.spinBox.setRange(-100, 100)
        self.spinBox.setValue(0)
        self.spinBox.valueChanged.connect(self.__handleSpinBox)
        # 保存MyTable的引用,方便后续获取模型
        self.table = MyTable(PandasModel, [[0,0,0], [0,0,0]])
        hbox = QHBoxLayout()
        hbox.addWidget(self.spinBox, 1)
        hbox.addWidget(self.table, 1)
        self.setLayout(hbox)

    def __handleSpinBox(self, value):
        # 通过table获取模型实例,再调用index方法创建索引
        model = self.table.model
        index = model.index(1, 1)
        # 用spinBox传来的value作为新值
        model.setData(index, value, Qt.EditRole)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    MW = MainWidget()
    MW.show()
    sys.exit(app.exec())

额外说明

  • dataChanged信号需要传递两个参数:变化区域的左上角和右下角索引,单个单元格时两个参数传同一个索引即可。
  • 确保操作的是模型实例而非类,这是Qt模型视图架构中最容易犯的错误之一。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 13:33:28