【问题标题】:why QWidgetTable does not refresh after closing tab in pyqt5?为什么在pyqt5中关闭选项卡后QWidgetTable不刷新?
【发布时间】:2022-11-04 21:57:20
【问题描述】:

下面的例子是我无法弄清楚的问题!如果有人可以帮助解决这个问题,我将不胜感激。我有一组数据,在这个例子中我从 csv 文件中读取。在下一步中,我将用数据填充我的 QWidgetTable。问题是当我更改数据并关闭选项卡并打开它时,数据不会刷新。 这是我的示例代码:

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.tab_test = QWidget()
        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)

        # table and button widget
        self.layout = QVBoxLayout()
        self.tabs.addTab(self.tab_test, 'Test')
        self.table = QTableWidget()
        self.layout.addWidget(self.table)
        self.tab_test.setLayout(self.layout)

        # fill headers
        self.table.setColumnCount(len(header))
        for i, field_name in enumerate(header):
            self.table.setHorizontalHeaderItem(i, QTableWidgetItem(field_name))

        # fill data
        for row, row_data in enumerate(data):
            self.table.insertRow(row)
            for col, data in enumerate(row_data):
                self.table.setItem(row, col, QTableWidgetItem(str(data)))


def main():
    app = QApplication([])
    ui = MainWindow()
    app.exec_()


if __name__ == '__main__':
    main()

这是样本数据:

import csv

data = [
    {
        'col_1': 1,
        'col_2': 2
    },
    {
        'col_1': 10,
        'col_2': 20
    },
    {
        'col_1': 100,
        'col_2': 200
    }
]

with open('test_data.csv', 'w', newline='\n') as f:
    header = data[0].keys()
    writer = csv.DictWriter(f, fieldnames=header)
    writer.writeheader()
    writer.writerows(data)

更新数据前:

但是在 csv 文件中更新 100 到 1000 和 200 到 2000 然后关闭选项卡并打开它后,数据已经更新但表的项目没有!

我错过了什么?

【问题讨论】:

    标签: python pyqt pyqt5


    【解决方案1】:

    您在MainWindow.setup_ui 分配一个QWidget 实例,就在这里:

    def setup_ui(self):
        # toolbar
        self.toolbar = self.addToolBar('Tool Bar')
        self.test_btn = QAction('Test', self)
        # .
        # .
    
        # tab
        self.tabs = QTabWidget() # <--
        # .
        # .
        # .
        self.setCentralWidget(self.tabs)
    

    这意味着您总是在QTabWidget 中一遍又一遍地添加相同的QWidget。因此,当您调用MainWindow.load_data 时,此函数调用self.tabs.addTab(tab_test, 'Test') 什么也不做,因为该小部件已经存在于表格小部件上。

    你应该做的是在MainWindow.load_data 中创建一个新的QWidget,就像这样:

    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
            toolbar = self.addToolBar('Tool Bar')
            test_btn = QAction('Test', self)
            toolbar.addAction(test_btn)
            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('
    ', '').split(',')
                for line in f:
                    data.append(line.replace('
    ', '').split(','))
            print(data)
    
            # table and button widget
            layout = QVBoxLayout()
            tab_test = QWidget()               ## MOVED THIS LINE FROM setup_ui
            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, data in enumerate(row_data):
                    table.setItem(row, col, QTableWidgetItem(str(data)))
    
    
    def main():
        app = QApplication([])
        ui = MainWindow()
        app.exec_()
    
    
    if __name__ == '__main__':
        main()
    

    请注意,我在 setup_uiload_data 范围内使用了局部变量。由于其中的大多数变量没有在其他MainWindow 方法中使用,因此不需要将它们存储到self,这与self.tabs 不同。此外,由于每个选项卡都应该相互独立,因此覆盖self.test_tab 变量并不是一件好事,除非您确实只需要存储最后添加的选项卡。

    【讨论】:

      猜你喜欢
      • 2021-11-20
      • 1970-01-01
      • 2015-01-24
      • 1970-01-01
      • 1970-01-01
      • 2020-07-05
      • 1970-01-01
      • 2016-12-31
      • 2010-10-22
      相关资源
      最近更新 更多