如何更新创建为 类 的 PyQt5 选项卡之间的值
How to update values between PyQt5 Tabs created as classes
我在 PyQT5 中创建了 2 个选项卡作为单独的 classes。 1 class (tab) 用于加载 excel 文件,其次用于设置删除不需要的行的规则。当我加载文件时,我需要 post 所有 header 到其他选项卡中的 QComboBox,以便我可以创建规则。不能让它工作。
import sys
from PyQt5.QtWidgets import *
import pandas as pd
class BOMAppWindow(QDialog):
def __init__(self):
super().__init__()
self.setGeometry(250, 150, 1400, 600)
mainTabWidget = QTabWidget() # --------- TABS UI ----------
mainTabWidget.addTab(FileOpenTab(), "File Open")
mainTabWidget.addTab(RowRemoveRulesTab(), "Row Delete Rules")
mainVbox = QVBoxLayout()
mainVbox.addWidget(mainTabWidget)
self.setLayout(mainVbox)
df = pd.DataFrame() # pandas dataframe as container for excel spreadsheet
header_list = []
class FileOpenTab(QDialog):
def __init__(self):
super().__init__()
vbox = QVBoxLayout()
h_top_box = QHBoxLayout()
excel_load_button = QPushButton("Open Excel File")
h_top_box.addWidget(excel_load_button) # ---- Adding Widgets to HBox
# ---------------- Adding Table Widget -----------
self.excel_table = QTableWidget()
vbox.addLayout(h_top_box) #-----Create Vertical Box Layout
vbox.addWidget(self.excel_table)
self.setLayout(vbox)
excel_load_button.clicked.connect(self.set_file_data)
# ----------- Open Excel Button Clicked Event
self.show()
def file_path(self): # ----------- file dialog box
filter_excel_only = "Excel Files (*.xlsx)"
filename = QFileDialog.getOpenFileName(self, 'Open Excel File', "", filter_excel_only)
return filename[0]
def set_file_data(self):
path_text = self.file_path()
if path_text:
global df
df = pd.read_excel(path_text, na_filter=False)
self.post_dataframe(df)
RowRemoveRulesTab().update_select_list()
def post_dataframe(self, dataframe):
column_count = dataframe.shape[1]
row_count = dataframe.shape[0]
self.excel_table.setColumnCount(column_count)
self.excel_table.setRowCount(row_count)
self.excel_table.setHorizontalHeaderLabels(list(dataframe.columns))
def header_list(self):
return list(df.columns)
class RowRemoveRulesTab(QDialog):
def __init__(self):
super().__init__()
hbox = QHBoxLayout()
groupBox1 = QGroupBox("Rule 1:")
vbox1 = QVBoxLayout()
self.rule1select = QComboBox()
self.rule1select.addItems(FileOpenTab().header_list())
vbox1.addWidget(self.rule1select)
groupBox1.setLayout(vbox1)
hbox.addWidget(groupBox1)
self.setLayout(hbox)
self.show()
def update_select_list(self):
self.rule1select.clear()
self.rule1select.addItems(FileOpenTab().header_list())
print(FileOpenTab().header_list())
app = QApplication(sys.argv)
bomAppWindow = BOMAppWindow()
bomAppWindow.show()
app.exec()
我需要第二个选项卡中的最后一个函数(或任何其他方式来处理它)update_select_list(自己):使用首先加载的 excel 文件中的 header 列表更新 QComboBox FileOpenTab class。现在 QComboBox 在文件加载后保持空白。
你的问题的关键点是你假设每次执行 FileOpenTab() 时它总是相同的小部件,但事实并非如此。 RowRemoveRulesTab 也是如此。相反,您必须将 object 存储在一个变量中并重新使用它。
另一方面你有设计问题,在这种情况下你必须使用Single responsibility principle,它表明每个class都有一个功能,并且必须为其他[=20=提供方法]s 来访问信息,在 Qt/PyQt 中,最简单的信息传输方式是通过信号,在这种情况下,当加载数据帧时,将使用新的 headers 发出信号,并且该信号必须是连接到另一个 class 的方法,以便它更新 QComboBox 的信息。
from PyQt5 import QtCore, QtGui, QtWidgets
import pandas as pd
class FileOpenTab(QtWidgets.QWidget):
headersChanged = QtCore.pyqtSignal(list)
def __init__(self, parent=None):
super(FileOpenTab, self).__init__(parent)
excel_load_button = QtWidgets.QPushButton(
"Open Excel File", clicked=self.load_file
)
self.excel_table = QtWidgets.QTableWidget()
lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(excel_load_button)
lay.addWidget(self.excel_table)
@QtCore.pyqtSlot()
def load_file(self):
filter_excel_only = "Excel Files (*.xlsx)"
filename, _ = QtWidgets.QFileDialog.getOpenFileName(
self, "Open Excel File", "", filter_excel_only
)
if filename:
df = pd.read_excel(filename, na_filter=False)
self.fill_table(df)
def fill_table(self, dataframe):
row_count, column_count = dataframe.shape
self.excel_table.setColumnCount(column_count)
self.excel_table.setRowCount(row_count)
headers = list(dataframe.columns)
self.excel_table.setHorizontalHeaderLabels(headers)
self.headersChanged.emit(headers)
class RowRemoveRulesTab(QtWidgets.QWidget):
def __init__(self, parent=None):
super(RowRemoveRulesTab, self).__init__(parent)
self.rule_select = QtWidgets.QComboBox()
group_box = QtWidgets.QGroupBox("Rule 1:")
vbox = QtWidgets.QVBoxLayout()
vbox.addWidget(self.rule_select)
group_box.setLayout(vbox)
lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(group_box)
@QtCore.pyqtSlot(list)
def update_items(self, items):
self.rule_select.clear()
self.rule_select.addItems(items)
class BOMAppWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(BOMAppWindow, self).__init__(parent)
file_open_tab = FileOpenTab()
row_remove_rules_tab = RowRemoveRulesTab()
file_open_tab.headersChanged.connect(row_remove_rules_tab.update_items)
mainTabWidget = QtWidgets.QTabWidget()
mainTabWidget.addTab(file_open_tab, "File Open")
mainTabWidget.addTab(row_remove_rules_tab, "Row Delete Rules")
self.setCentralWidget(mainTabWidget)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = BOMAppWindow()
w.show()
sys.exit(app.exec_())
我在 PyQT5 中创建了 2 个选项卡作为单独的 classes。 1 class (tab) 用于加载 excel 文件,其次用于设置删除不需要的行的规则。当我加载文件时,我需要 post 所有 header 到其他选项卡中的 QComboBox,以便我可以创建规则。不能让它工作。
import sys
from PyQt5.QtWidgets import *
import pandas as pd
class BOMAppWindow(QDialog):
def __init__(self):
super().__init__()
self.setGeometry(250, 150, 1400, 600)
mainTabWidget = QTabWidget() # --------- TABS UI ----------
mainTabWidget.addTab(FileOpenTab(), "File Open")
mainTabWidget.addTab(RowRemoveRulesTab(), "Row Delete Rules")
mainVbox = QVBoxLayout()
mainVbox.addWidget(mainTabWidget)
self.setLayout(mainVbox)
df = pd.DataFrame() # pandas dataframe as container for excel spreadsheet
header_list = []
class FileOpenTab(QDialog):
def __init__(self):
super().__init__()
vbox = QVBoxLayout()
h_top_box = QHBoxLayout()
excel_load_button = QPushButton("Open Excel File")
h_top_box.addWidget(excel_load_button) # ---- Adding Widgets to HBox
# ---------------- Adding Table Widget -----------
self.excel_table = QTableWidget()
vbox.addLayout(h_top_box) #-----Create Vertical Box Layout
vbox.addWidget(self.excel_table)
self.setLayout(vbox)
excel_load_button.clicked.connect(self.set_file_data)
# ----------- Open Excel Button Clicked Event
self.show()
def file_path(self): # ----------- file dialog box
filter_excel_only = "Excel Files (*.xlsx)"
filename = QFileDialog.getOpenFileName(self, 'Open Excel File', "", filter_excel_only)
return filename[0]
def set_file_data(self):
path_text = self.file_path()
if path_text:
global df
df = pd.read_excel(path_text, na_filter=False)
self.post_dataframe(df)
RowRemoveRulesTab().update_select_list()
def post_dataframe(self, dataframe):
column_count = dataframe.shape[1]
row_count = dataframe.shape[0]
self.excel_table.setColumnCount(column_count)
self.excel_table.setRowCount(row_count)
self.excel_table.setHorizontalHeaderLabels(list(dataframe.columns))
def header_list(self):
return list(df.columns)
class RowRemoveRulesTab(QDialog):
def __init__(self):
super().__init__()
hbox = QHBoxLayout()
groupBox1 = QGroupBox("Rule 1:")
vbox1 = QVBoxLayout()
self.rule1select = QComboBox()
self.rule1select.addItems(FileOpenTab().header_list())
vbox1.addWidget(self.rule1select)
groupBox1.setLayout(vbox1)
hbox.addWidget(groupBox1)
self.setLayout(hbox)
self.show()
def update_select_list(self):
self.rule1select.clear()
self.rule1select.addItems(FileOpenTab().header_list())
print(FileOpenTab().header_list())
app = QApplication(sys.argv)
bomAppWindow = BOMAppWindow()
bomAppWindow.show()
app.exec()
我需要第二个选项卡中的最后一个函数(或任何其他方式来处理它)update_select_list(自己):使用首先加载的 excel 文件中的 header 列表更新 QComboBox FileOpenTab class。现在 QComboBox 在文件加载后保持空白。
你的问题的关键点是你假设每次执行 FileOpenTab() 时它总是相同的小部件,但事实并非如此。 RowRemoveRulesTab 也是如此。相反,您必须将 object 存储在一个变量中并重新使用它。
另一方面你有设计问题,在这种情况下你必须使用Single responsibility principle,它表明每个class都有一个功能,并且必须为其他[=20=提供方法]s 来访问信息,在 Qt/PyQt 中,最简单的信息传输方式是通过信号,在这种情况下,当加载数据帧时,将使用新的 headers 发出信号,并且该信号必须是连接到另一个 class 的方法,以便它更新 QComboBox 的信息。
from PyQt5 import QtCore, QtGui, QtWidgets
import pandas as pd
class FileOpenTab(QtWidgets.QWidget):
headersChanged = QtCore.pyqtSignal(list)
def __init__(self, parent=None):
super(FileOpenTab, self).__init__(parent)
excel_load_button = QtWidgets.QPushButton(
"Open Excel File", clicked=self.load_file
)
self.excel_table = QtWidgets.QTableWidget()
lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(excel_load_button)
lay.addWidget(self.excel_table)
@QtCore.pyqtSlot()
def load_file(self):
filter_excel_only = "Excel Files (*.xlsx)"
filename, _ = QtWidgets.QFileDialog.getOpenFileName(
self, "Open Excel File", "", filter_excel_only
)
if filename:
df = pd.read_excel(filename, na_filter=False)
self.fill_table(df)
def fill_table(self, dataframe):
row_count, column_count = dataframe.shape
self.excel_table.setColumnCount(column_count)
self.excel_table.setRowCount(row_count)
headers = list(dataframe.columns)
self.excel_table.setHorizontalHeaderLabels(headers)
self.headersChanged.emit(headers)
class RowRemoveRulesTab(QtWidgets.QWidget):
def __init__(self, parent=None):
super(RowRemoveRulesTab, self).__init__(parent)
self.rule_select = QtWidgets.QComboBox()
group_box = QtWidgets.QGroupBox("Rule 1:")
vbox = QtWidgets.QVBoxLayout()
vbox.addWidget(self.rule_select)
group_box.setLayout(vbox)
lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(group_box)
@QtCore.pyqtSlot(list)
def update_items(self, items):
self.rule_select.clear()
self.rule_select.addItems(items)
class BOMAppWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(BOMAppWindow, self).__init__(parent)
file_open_tab = FileOpenTab()
row_remove_rules_tab = RowRemoveRulesTab()
file_open_tab.headersChanged.connect(row_remove_rules_tab.update_items)
mainTabWidget = QtWidgets.QTabWidget()
mainTabWidget.addTab(file_open_tab, "File Open")
mainTabWidget.addTab(row_remove_rules_tab, "Row Delete Rules")
self.setCentralWidget(mainTabWidget)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = BOMAppWindow()
w.show()
sys.exit(app.exec_())