PyQt5:关闭标签页后重开,QTableWidget数据不刷新的问题
问题:PyQt5中重新打开标签页后QTableWidget数据不刷新
在PyQt5开发中,从CSV文件读取数据填充QTableWidget,修改CSV文件内容后关闭标签页再重新打开,控制台打印的CSV数据已更新,但表格显示的内容依旧是旧数据。
原代码问题分析
问题出在标签页控件的复用上:
- 初始化时创建的
self.tab_test是全局唯一的QWidget对象,第一次添加到TabWidget后,关闭标签只是从TabWidget中移除它的显示,但该对象本身仍然存在且保留着旧的表格控件。 - 再次调用
load_data时,又将同一个self.tab_test添加到TabWidget,此时布局已经绑定了旧表格,新创建的表格无法替换掉旧的显示内容。
修复后的代码
from PyQt5.QtWidgets import QMainWindow, QApplication, QWidget, QVBoxLayout from PyQt5.QtWidgets import QAction, QTabWidget, QTableWidget, QTableWidgetItem class MainWindow(QMainWindow): def __init__(self): super().__init__() self.setGeometry(100, 100, 400, 400) self.setup_ui() self.show() def setup_ui(self): # toolbar self.toolbar = self.addToolBar('Tool Bar') self.test_btn = QAction('Test', self) self.toolbar.addAction(self.test_btn) self.test_btn.triggered.connect(self.load_data) # tab self.tabs = QTabWidget() self.tabs.setTabsClosable(True) self.tabs.tabCloseRequested.connect(lambda tab_index: self.tabs.removeTab(tab_index)) self.setCentralWidget(self.tabs) def load_data(self): # get data data = [] with open('test_data.csv', 'r') as f: header = next(f).replace('\n', '').split(',') for line in f: data.append(line.replace('\n', '').split(',')) print(data) # 每次加载都创建新的标签页控件,避免复用旧对象 tab_test = QWidget() layout = QVBoxLayout() self.tabs.addTab(tab_test, 'Test') # 创建新表格并填充数据 table = QTableWidget() layout.addWidget(table) tab_test.setLayout(layout) # fill headers table.setColumnCount(len(header)) for i, field_name in enumerate(header): table.setHorizontalHeaderItem(i, QTableWidgetItem(field_name)) # fill data for row, row_data in enumerate(data): table.insertRow(row) for col, cell_data in enumerate(row_data): table.setItem(row, col, QTableWidgetItem(str(cell_data))) def main(): app = QApplication([]) ui = MainWindow() app.exec_() if __name__ == '__main__': main()
关键修改点
- 移除全局的
self.tab_test:改为在load_data函数内每次创建新的QWidget作为标签页内容,确保每次打开的标签页都是全新的控件实例。 - 避免布局复用:新标签页使用新的布局和表格控件,确保每次都能加载最新的CSV数据并渲染。
进阶优化(可选)
如果不想重复创建同名标签,可以添加逻辑检查是否已存在"Test"标签,存在则切换到该标签并刷新表格数据:
def load_data(self): # 先检查是否存在Test标签 for i in range(self.tabs.count()): if self.tabs.tabText(i) == 'Test': # 获取已存在的标签页和表格 tab_widget = self.tabs.widget(i) table = tab_widget.findChild(QTableWidget) # 刷新表格数据 self.refresh_table(table) self.tabs.setCurrentIndex(i) return # 不存在则创建新标签 data = [] with open('test_data.csv', 'r') as f: header = next(f).replace('\n', '').split(',') for line in f: data.append(line.replace('\n', '').split(',')) tab_test = QWidget() layout = QVBoxLayout() self.tabs.addTab(tab_test, 'Test') table = QTableWidget() layout.addWidget(table) tab_test.setLayout(layout) self.fill_table(table, header, data) def fill_table(self, table, header, data): # 填充表头和数据的通用方法 table.setColumnCount(len(header)) for i, field_name in enumerate(header): table.setHorizontalHeaderItem(i, QTableWidgetItem(field_name)) table.setRowCount(len(data)) for row, row_data in enumerate(data): for col, cell_data in enumerate(row_data): table.setItem(row, col, QTableWidgetItem(str(cell_data))) def refresh_table(self, table): # 刷新表格数据的方法 data = [] with open('test_data.csv', 'r') as f: header = next(f).replace('\n', '').split(',') for line in f: data.append(line.replace('\n', '').split(',')) table.clearContents() self.fill_table(table, header, data)
内容的提问来源于stack exchange,提问作者Rahman Tavakoli
相关产品推荐
相关产品推荐

