QTableView的ComboBox代理模型与PandasModel不同步问题求助
嗨,我看了你的问题,这其实是Qt中代理模型索引映射的典型坑,我来帮你一步步捋清楚怎么解决:
首先得点明问题根源:你现在把ComboBoxDelegate绑定到了原始的self.model(也就是PandasModel)上,但你的表格实际用的是proxyModel(MySortFilterProxyModel)来做排序和过滤。当表格排序后,视图里的行号是代理模型的行号,和原始PandasModel的行号已经不一一对应了,这时候你用代理里拿到的索引直接去操作原始模型,肯定会把数据写到错误的行里,自然就出现了显示不同步的情况。
接下来给你具体的修改方案:
第一步:让ComboBox代理绑定到代理模型而非原始模型
你创建代理的代码要改成把proxyModel传进去,而不是原始的self.model:self.area_delegate = ComboBoxDelegate(self.area_list, self.proxyModel) self.county_delegate = ComboBoxDelegate(self.county_dict, self.proxyModel)第二步:在Delegate的
setModelData方法中做索引映射
当你要把ComboBox选中的值保存到模型时,必须把代理模型的索引转换成原始模型的索引,再去更新数据。比如在你的ComboBoxDelegate的setModelData方法里,要加这段转换逻辑:def setModelData(self, editor, model, index): value = editor.currentText() # 把代理模型的索引映射回原始PandasModel的索引 source_index = model.mapToSource(index) # 用转换后的索引去更新原始模型 source_model = model.sourceModel() source_model.setData(source_index, value, Qt.EditRole)第三步:确保PandasModel正确发出数据变更信号
你的PandasModel在setData方法修改完DataFrame后,一定要发出dataChanged信号,这样代理模型才能感知到数据变化并同步视图。比如:class PandasModel(QAbstractTableModel): # ... 其他代码 ... def setData(self, index, value, role=Qt.EditRole): if role == Qt.EditRole: # 修改DataFrame的对应单元格 self.df.iloc[index.row(), index.column()] = value # 发出数据变更信号 self.dataChanged.emit(index, index) return True return False第四步:检查代理模型的索引映射是否正常
如果你是继承QSortFilterProxyModel实现的MySortFilterProxyModel,那mapToSource和mapFromSource方法默认是正常工作的,但如果你重写了rowCount、index等核心方法,一定要确保没有破坏索引映射逻辑。
最后给你个调试小技巧:可以在Delegate的setModelData里打印一下代理索引和转换后的原始索引,看看行号是否对应正确,比如:
print(f"代理行号:{index.row()},原始行号:{source_index.row()}")
备注:内容来源于stack exchange,提问作者Tadpole

