PyQt5中QTableWidget筛选函数filterdata报KeyError:1的问题
PyQt5 QTableWidget筛选功能KeyError问题修复
问题描述
参考PyQt4的QTableWidget筛选方案适配PyQt5时,执行filterdata函数抛出KeyError:1。点击第一列表头并勾选筛选选项后,self.keywords初始化正常,但循环到j=1时触发错误,与复选框是否勾选无关。
报错核心代码
def filterdata(self): columnsShow = dict([(i, True) for i in range(self.qPerformanceReport_table.rowCount())]) for i in range(self.qPerformanceReport_table.rowCount()): for j in range(self.qPerformanceReport_table.columnCount()): item = self.qPerformanceReport_table.item(i, j) if self.keywords[j]: if item.text() not in self.keywords[j]: columnsShow[i] = False for key, value in enumerate(columnsShow[:]): self.qPerformanceReport_table.setRowHidden(key, not value)
问题原因
- 字典键缺失:
self.keywords在__init__中初始化时,表格尚未加载数据,columnCount()返回0,导致self.keywords是空字典。后续加载表格数据后未更新该字典,遍历列时j=1、j=2等键不存在,触发KeyError。 - 字典遍历逻辑错误:
enumerate(columnsShow[:])写法错误,字典不支持切片操作,会导致遍历逻辑异常。 - 变量名笔误:
refresh_performance_report中使用了未定义的df_agg1,实际应为df_agg。
修复步骤
1. 修正self.keywords初始化时机
将self.keywords的初始化移到表格数据加载完成后,确保键与列数匹配:
def refresh_performance_report(self): df_agg = pd.DataFrame(np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]), columns=['a', 'b', 'c']) nRows, nColumns = df_agg.shape self.qPerformanceReport_table.setColumnCount(nColumns) self.qPerformanceReport_table.setRowCount(nRows) self.qPerformanceReport_table.setHorizontalHeaderLabels(df_agg.columns) # 初始化/更新keywords字典 self.keywords = {i: [] for i in range(nColumns)} for i in range(self.qPerformanceReport_table.rowCount()): for j in range(self.qPerformanceReport_table.columnCount()): # 修正变量名笔误 self.qPerformanceReport_table.setItem(i, j, QtWidgets.QTableWidgetItem(str(df_agg.iloc[i, j]))) for j in range(self.qPerformanceReport_table.columnCount()): self.qPerformanceReport_table.resizeColumnToContents(j)
2. 修复filterdata函数逻辑
def filterdata(self): # 初始化所有行显示状态为True columnsShow = {i: True for i in range(self.qPerformanceReport_table.rowCount())} for i in range(self.qPerformanceReport_table.rowCount()): for j in range(self.qPerformanceReport_table.columnCount()): item = self.qPerformanceReport_table.item(i, j) # 先检查j是否在keywords中,避免KeyError if j in self.keywords and self.keywords[j]: if item.text() not in self.keywords[j]: columnsShow[i] = False # 正确遍历字典设置行隐藏状态 for row_idx, show in columnsShow.items(): self.qPerformanceReport_table.setRowHidden(row_idx, not show)
3. 初始化时设置空字典兜底
在__init__中先初始化空字典,避免提前调用函数时出错:
def __init__(self): super(MyQtApp, self).__init__() self.setupUi(self) self.qPerformanceReport_refresh.clicked.connect(self.refresh_performance_report) self.horizontalHeader=self.qPerformanceReport_table.horizontalHeader() self.horizontalHeader.sectionClicked.connect(self.on_view_horizontalHeader_sectionClicked) # 初始化为空字典,后续加载数据时更新 self.keywords = {} self.checkBoxs = [] self.col = None
完整修复后代码
class MyQtApp(main.Ui_MainWindow, QtWidgets.QMainWindow): def __init__(self): super(MyQtApp, self).__init__() self.setupUi(self) self.qPerformanceReport_refresh.clicked.connect(self.refresh_performance_report) self.horizontalHeader=self.qPerformanceReport_table.horizontalHeader() self.horizontalHeader.sectionClicked.connect(self.on_view_horizontalHeader_sectionClicked) self.keywords = {} self.checkBoxs = [] self.col = None def refresh_performance_report(self): df_agg = pd.DataFrame(np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]), columns=['a', 'b', 'c']) nRows, nColumns = df_agg.shape self.qPerformanceReport_table.setColumnCount(nColumns) self.qPerformanceReport_table.setRowCount(nRows) self.qPerformanceReport_table.setHorizontalHeaderLabels(df_agg.columns) # 更新keywords字典 self.keywords = {i: [] for i in range(nColumns)} for i in range(self.qPerformanceReport_table.rowCount()): for j in range(self.qPerformanceReport_table.columnCount()): self.qPerformanceReport_table.setItem(i, j, QtWidgets.QTableWidgetItem(str(df_agg.iloc[i, j]))) for j in range(self.qPerformanceReport_table.columnCount()): self.qPerformanceReport_table.resizeColumnToContents(j) def slotSelect(self, state): for checkbox in self.checkBoxs: checkbox.setChecked(Qt.Qt.Checked == state) def on_view_horizontalHeader_sectionClicked(self, index): self.menu = QtWidgets.QMenu(self) self.col = index data_unique = [] self.checkBoxs = [] checkBox = QtWidgets.QCheckBox("Select all", self.menu) checkableAction = QtWidgets.QWidgetAction(self.menu) checkableAction.setDefaultWidget(checkBox) self.menu.addAction(checkableAction) checkBox.setChecked(True) checkBox.stateChanged.connect(self.slotSelect) for i in range(self.qPerformanceReport_table.rowCount()): if not self.qPerformanceReport_table.isRowHidden(i): item = self.qPerformanceReport_table.item(i, index) if item.text() not in data_unique: data_unique.append(item.text()) checkBox = QtWidgets.QCheckBox(item.text(), self.menu) checkBox.setChecked(True) checkableAction = QtWidgets.QWidgetAction(self.menu) checkableAction.setDefaultWidget(checkBox) self.menu.addAction(checkableAction) self.checkBoxs.append(checkBox) btn = QtWidgets.QDialogButtonBox(QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Cancel, Qt.Qt.Horizontal, self.menu) btn.accepted.connect(self.menuClose) btn.rejected.connect(self.menu.close) checkableAction = QtWidgets.QWidgetAction(self.menu) checkableAction.setDefaultWidget(btn) self.menu.addAction(checkableAction) headerPos = self.qPerformanceReport_table.mapToGlobal(self.horizontalHeader.pos()) posY = headerPos.y() + self.horizontalHeader.height() posX = headerPos.x() + self.horizontalHeader.sectionPosition(index) self.menu.exec_(QtCore.QPoint(posX, posY)) def menuClose(self): if self.col not in self.keywords: self.keywords[self.col] = [] self.keywords[self.col] = [] for element in self.checkBoxs: if element.isChecked(): self.keywords[self.col].append(element.text()) self.filterdata() self.menu.close() def clearFilter(self): for i in range(self.qPerformanceReport_table.rowCount()): self.qPerformanceReport_table.setRowHidden(i, False) def filterdata(self): columnsShow = {i: True for i in range(self.qPerformanceReport_table.rowCount())} for i in range(self.qPerformanceReport_table.rowCount()): for j in range(self.qPerformanceReport_table.columnCount()): item = self.qPerformanceReport_table.item(i, j) if j in self.keywords and self.keywords[j]: if item.text() not in self.keywords[j]: columnsShow[i] = False for row_idx, show in columnsShow.items(): self.qPerformanceReport_table.setRowHidden(row_idx, not show)
内容的提问来源于stack exchange,提问作者Hotone
相关产品推荐
相关产品推荐

