PyQt5中QTableWidget无法多次刷新加载数据的问题排查
解决QTableWidget刷新后不显示新数据的问题
我帮你揪出问题根源了!核心问题在于你复用了同一个tab2实例,第二次筛选数据时,新创建的TableWidget并没有被添加到标签页的布局里,布局里还是之前那个被清空的旧表格控件,所以看不到新数据。
问题细节拆解
- 第一次点击"Select Group"时,你给tab2添加了布局和tableWidget,一切正常显示。
- 点击"Refresh"后,你清空了标签页切回分组选择页,但tab2里的旧布局和空表格并没有被清除。
- 再次点击"Select Group"时,你创建了新的TableWidget并赋值给
self.tab2.tableWidget,但这个新控件并没有被加入到tab2的布局中——布局里还是那个被你清空行的旧表格,自然看不到新数据。
修复方案
最简单的解决办法是每次筛选数据时都重新创建一个全新的tab2对象,而不是复用初始化时的那个,这样每次生成的标签页都是干净的,不会残留旧控件。
下面是修改后的完整代码,我标注了关键修改点:
import sys from PyQt5 import QtWidgets, QtGui, QtCore import pandas as pd class TableWidget(QtWidgets.QTableWidget): def __init__(self, tab2_df, parent=None): super().__init__(parent) nRows = len(tab2_df.index) nColumns = len(tab2_df.columns) self.setRowCount(nRows) self.setColumnCount(nColumns) for i in range(self.rowCount()): for j in range(self.columnCount()): x = "{}".format(tab2_df.iloc[i, j]) self.setItem(i, j, QtWidgets.QTableWidgetItem(x)) print(tab2_df) # 验证新数据是否正确获取 class Window(QtWidgets.QMainWindow): def __init__(self, parent=None): super().__init__() self.title = "Reporting Test" self.left = 400 self.top = 50 self.width = 1300 self.height = 700 self.setWindowTitle(self.title) self.setGeometry(self.left, self.top, self.width, self.height) self.table_widget = MyTableWidget(self) self.setCentralWidget(self.table_widget) self.show() class MyTableWidget(QtWidgets.QWidget): def __init__(self, parent): super().__init__(parent) self.layout = QtWidgets.QVBoxLayout(self) self.tabs = QtWidgets.QTabWidget() self.tab1 = QtWidgets.QWidget() # 分组选择标签页 # 移除初始化时的tab2,改为每次筛选时创建 # self.tab2 = QtWidgets.QWidget() self.tabs.addTab(self.tab1,"Group Select") self.layout.addWidget(self.tabs) self.setLayout(self.layout) # 示例DataFrame self.tab1.df = pd.DataFrame({'Name':['Tom', 'Jack', 'Steve', 'Ricky'],'Age':[28,34,29,42]}) self.tab1.group = self.tab1.df[["Name"]] self.tab1.groupList = self.tab1.group['Name'].tolist() self.tab1.listLabel = ["",] * len(self.tab1.groupList) self.tab1.grid = QtWidgets.QGridLayout() self.tab1.setLayout(self.tab1.grid) # 创建复选框 for i, v in enumerate(self.tab1.groupList): self.tab1.groupList[i] = QtWidgets.QCheckBox(v) self.tab1.listLabel[i] = QtWidgets.QLabel() self.tab1.grid.addWidget(self.tab1.groupList[i], i, 0) self.tab1.button = QtWidgets.QPushButton("Select Group") self.tab1.button.clicked.connect(self.checkboxChanged) self.tab1.labelResult = QtWidgets.QLabel() self.tab1.grid.addWidget(self.tab1.button, len(self.tab1.groupList)+1, 0, 1,2) self.tab1.setLayout(self.tab1.grid) def checkboxChanged(self): self.tabs.clear() # 关键修改:每次筛选都创建新的tab2 self.tab2 = QtWidgets.QWidget() self.tabs.addTab(self.tab2,"Loaded Data") # 简化筛选逻辑(可选优化,比原逻辑更可靠) selected_names = [cb.text() for cb in self.tab1.groupList if cb.isChecked()] tab2_df = self.tab1.df[self.tab1.df["Name"].isin(selected_names)] # 创建新表格并添加到新tab2的布局 self.tab2.tableWidget = TableWidget(tab2_df, self) self.tab2.tableWidget.setHorizontalHeaderLabels(("Name", "Age")) stylesheet3 = "::section{font: bold 18px}" self.tab2.tableWidget.horizontalHeader().setStyleSheet(stylesheet3) self.tab2.button = QtWidgets.QPushButton("Refresh", self.tab2) self.tab2.button.clicked.connect(self.refresh_button) self.tab2.layout = QtWidgets.QVBoxLayout() self.tab2.layout.addWidget(self.tab2.tableWidget) self.tab2.layout.addWidget(self.tab2.button) self.tab2.setLayout(self.tab2.layout) def refresh_button(self): self.tabs.clear() # 移除不必要的清空行操作,因为下次筛选会创建全新的表格 # self.tab2.tableWidget.setRowCount(0) self.tabs.addTab(self.tab1,"Group Select") if __name__ == '__main__': app = QtWidgets.QApplication(sys.argv) window = Window() window.show() sys.exit(app.exec_())
额外优化说明
我还帮你简化了筛选逻辑:直接遍历复选框收集选中的名称,不用通过Label文本判断,这样代码更简洁也更可靠。
现在你每次点击"Select Group"都会生成一个全新的标签页,里面的表格也是最新的,刷新后再筛选就能正常显示数据了!
内容的提问来源于stack exchange,提问作者undeadsmarties
相关产品推荐
相关产品推荐

