首页 > 解决方案 > 有没有办法多次写入 qTableWidget ?

问题描述

我正在尝试在 PyQt5 中创建一个 qTableWidget,它允许我使用过滤 Pandas DataFrame 的复选框进行选择,然后在 GUI 中显示该数据。

我可以让它第一次运行代码,它会像我期望的那样呈现数据。但是,当您尝试刷新它时,它不会将新数据加载到 qTableWidget 中。没有任何错误消息,如果您打印 DataFrame 它正在加载新数据,正如我所期望的那样,它只是没有显示在 GUI 中。

我在这里搜索了类似的问题,但找不到任何人遇到与我相同的问题。

I need it to refresh the table in the same GUI as in my real data, the DataFrame is generated from an API call which when selecting a new group will pull the most recent data and could be ran an indefinite number of times.

这是我要做的,我试图添加评论以尽可能多地解释

import sys
from PyQt5 import QtWidgets, QtGui, QtCore
import pandas as pd

class TableWidget(QtWidgets.QTableWidget):
    def __init__(self, tab2_df, parent=None):
        QtWidgets.QTableWidget.__init__(self,parent)

        tab2_df = tab2_df
        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) #validating that the new df is received

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)

        #initialize window with tabs
        self.table_widget = MyTableWidget(self)
        self.setCentralWidget(self.table_widget)

        self.show()

class MyTableWidget(QtWidgets.QWidget):

    def __init__(self, parent):
        super(QtWidgets.QWidget, self).__init__(parent)
        self.layout = QtWidgets.QVBoxLayout(self)
        self.tabs = QtWidgets.QTabWidget()
        self.tab1 = QtWidgets.QWidget() #Group select Tab
        self.tab2 = QtWidgets.QWidget() #DataFrame Tab

        # Name and add first Tab to Layout
        self.tabs.addTab(self.tab1,"Group Select")
        self.layout.addWidget(self.tabs)
        self.setLayout(self.layout)

        # Sample DataFrame for demonstation
        self.tab1.df = pd.DataFrame({'Name':['Tom', 'Jack', 'Steve', 'Ricky'],'Age':[28,34,29,42]})

        # Filter dataframe into a list to show as checkboxes
        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)

        # Populate the checkboxes with the list
        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)

        # Add the checkboxes into the tab
        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,     i+1, 0, 1,2)
        self.tab1.setLayout(self.tab1.grid)

    def checkboxChanged(self):
        # Clear the previous tab
        self.tabs.clear()
        # Add a new tab for the loaded data
        self.tabs.addTab(self.tab2,"Loaded Data")

        # Match the ticked checkbox to the DataFrame and filter to a new DataFrame
        self.tab1.labelResult.setText("")
        for i, v in enumerate(self.tab1.groupList):
            self.tab1.listLabel[i].setText("True" if v.checkState() else "False")
            self.tab1.labelResult.setText("{}, {}".format(self.tab1.labelResult.text(),
                                                     self.tab1.listLabel[i].text()))

        self.tab1.groupList2 = self.tab1.group['Name'].tolist()

        checked2 = str(self.tab1.labelResult.text()).split(',')
        result = list(filter(None, checked2))
        checked_list = {"Name":self.tab1.groupList2, "checked":result}
        checked_list_df = pd.DataFrame(checked_list)
        checked_list_filtered_df = checked_list_df[checked_list_df.checked.str.contains("true", case=False)]
        self.tab1.filteredGroup_df = checked_list_filtered_df
        group_select_df = pd.merge(self.tab1.group, self.tab1.filteredGroup_df, on="Name", how="inner")
        group_select_list = group_select_df["Name"].tolist()
        tab2_df = self.tab1.df[self.tab1.df["Name"].isin(group_select_list)]

        # Populate the filtered DataFrame onto a TableWidget and populate this into the tab
        self.tab2.tableWidget = TableWidget(tab2_df, self)

        # Set headings and style for TableWidget
        self.tab2.tableWidget.setHorizontalHeaderLabels(("Name", "Age"))
        stylesheet3 = "::section{font: bold 18px}"
        self.tab2.tableWidget.horizontalHeader().setStyleSheet(stylesheet3)
        # Add button to refresh the data with a new group filter
        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)

        # Refresh button that will clear the previous TableWidget and load the Group Select Tab to generate new data
    def refresh_button(self):
        # Clear the previous tab
        self.tabs.clear()
        # Clear the TableWidget
        self.tab2.tableWidget.setRowCount(0)
        # Load the Group Select Tab to select the new group
        self.tabs.addTab(self.tab1,"Group Select")

if __name__ == '__main__':

    app = QtWidgets.QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(app.exec_())

我敢肯定,很多事情都可以做得更优雅,我正在努力学习,但我就是想不通这一点。

标签: python-3.xpandaspyqt5

解决方案


推荐阅读