PySide6/QTableView更新失败:index方法调用触发TypeError
解决QAbstractTableModel调用index时的TypeError及相关问题
核心错误原因
你触发的TypeError,是因为直接调用了PandasModel类的index方法,而index是QAbstractTableModel实例的方法,必须通过模型对象来调用,不能用类本身。同时你的代码还有几个其他问题导致功能无法正常工作:
具体修复步骤
保存模型实例的引用
在MainWidget中,你创建了MyTable但没有保存它的模型实例,而且self.pandasModel赋值的是类而非实例。需要修改MainWidget的初始化代码,保存MyTable的引用,后续通过它获取模型实例。正确创建QModelIndex对象
要获取表格的索引,需要调用模型实例的index()方法,而不是类的。修复DataFrame赋值方式
setData中用self._data[row][column] = value会触发Pandas的链式索引警告,应该改用iloc进行位置赋值。修正未定义的变量
__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
相关产品推荐
相关产品推荐

