如何仅更新QTableView中变动的数据(Python)
解决方案
针对每次重置模型导致选中状态丢失的问题,核心是复用现有模型实例,通过Qt模型的信号机制仅更新变动数据,无需重新创建模型。以下是具体改造方案:
1. 修改现有pandasModel,添加数据更新方法
在你的模型类中新增update_data方法,处理行增减和单元格值变动,并触发对应Qt信号:
class pandasModel(QAbstractTableModel): # 保留原有所有方法... def update_data(self, new_data): # 处理行数量变化 old_row_count = self._data.shape[0] new_row_count = new_data.shape[0] if new_row_count > old_row_count: # 插入新增行 self.beginInsertRows(QtCore.QModelIndex(), old_row_count, new_row_count - 1) self._data = pd.concat([self._data, new_data.iloc[old_row_count:]]) self.endInsertRows() elif new_row_count < old_row_count: # 删除多余行 self.beginRemoveRows(QtCore.QModelIndex(), new_row_count, old_row_count - 1) self._data = self._data.iloc[:new_row_count] self.endRemoveRows() else: # 行数量不变,直接替换数据 self._data = new_data.copy() # 触发数据更新信号 if old_row_count == new_row_count: # 触发全量数据更新信号(若需精确更新可替换为下方优化逻辑) top_left = self.index(0, 0) bottom_right = self.index(new_row_count - 1, self._data.shape[1] - 1) self.dataChanged.emit(top_left, bottom_right, [Qt.DisplayRole])
精确更新优化(可选)
如果数据量极大,全量触发dataChanged效率不高,可以用pd.DataFrame.compare定位仅变动的单元格:
def update_data(self, new_data): # 先处理行增减逻辑(同上) old_row_count = self._data.shape[0] new_row_count = new_data.shape[0] if new_row_count != old_row_count: # 行数量变动处理逻辑(同上) # ... # 仅当行列数不变时执行精确对比 if old_row_count == new_row_count and self._data.columns.equals(new_data.columns): # 获取所有变动的单元格 diff = self._data.compare(new_data) for (row_idx, col_name), _ in diff.stack().items(): col_idx = self._data.columns.get_loc(col_name) cell_index = self.index(row_idx, col_idx) self.dataChanged.emit(cell_index, cell_index, [Qt.DisplayRole]) self._data = new_data.copy()
2. 调整表格更新逻辑
初始化时创建一次模型,后续更新直接调用update_data:
# 初始化表格模型(仅执行一次) self.model = pandasModel(self.myDataFrame) self.Table.setModel(self.model) # 线程获取新数据后,必须在主线程执行更新(可通过Qt信号槽或QMetaObject.invokeMethod切换线程) self.model.update_data(new_dataframe)
关键说明
- 选中状态会被保留,因为模型实例未被替换,仅更新数据内容。
- 所有Qt模型信号必须在主线程发出,线程传递数据后需切换到主线程执行
update_data。
内容的提问来源于stack exchange,提问作者Pratik Bhadane
相关产品推荐
相关产品推荐

