python-3.x - 有没有办法多次写入 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_())
我敢肯定,很多事情都可以做得更优雅,我正在努力学习,但我就是想不通这一点。
解决方案
推荐阅读
- excel - 对象在循环内的 IF 语句中不支持此属性/方法
- javascript - 循环通过开放层特征对象数组
- javascript - 图标传单地图javascript
- symmetricds - Symmetricds 支持空间数据库?
- java - 我不明白复制构造函数是如何工作的
- jquery - JQuery保存文件并从中读取而不是每次都打开新版本
- amazon-web-services - 跨账户 IAM 访问被 GUI 客户端拒绝,但通过 CLI 允许
- python - 如何在 Python 的不同目录中读取/创建文件
- android - 是否可以在android中同时从两个后置摄像头获取信息?
- python - 将字符串从变量保存到 .txt 并检查变量是否与下一个循环中已使用的字符串匹配