如何在 PyQt5 中的两个 类 之间来回传递变量?
How can I pass variables back and forth between two classes in PyQt5?
我正在开发一个用于导入和绘制数据(csv 文件)的 GUI。数据最初使用 getfile()
和 on_pushButtonLoad_clicked()
在 TabWidget()
class 中导入,然后传递到 FirstTab()
class,其中 MRChart()
是绘制在 infrastructure()
小部件中。为此,我在 TabWidget()
中创建了 firstTab
实例(如果我的术语在这里不正确,请见谅)。
最终目标是根据在范围滑块上选择的数值范围更新绘图。首先,我想将 slider1
的值传递给 FirstTab()
,我应该可以从那里进行管理。为此,我尝试在 FirstTab()
中创建 tabwidget
实例。但是,我得到以下信息:“RecursionError:超出最大递归深度”。我认为这是由于每个 class 都有一个自己的实例包含在另一个中。
感谢任何帮助。
代码:
class TabWidget(QDialog):
def __init__(self, data):
super(TabWidget, self).__init__()
self.data = data
self.firstTab = FirstTab(self.data)
self.showMaximized()
# create Header
FilterLayout = QHBoxLayout()
FilterLayout.addWidget(self.createHeader1a(), 1)
FilterLayout.addWidget(self.createHeader2a(), 4)
# create Tab
tabwidget = QTabWidget()
tabwidget.addTab(self.firstTab, "Tab 1")
vbox = QVBoxLayout()
vbox.addLayout(FilterLayout)
vbox.addWidget(tabwidget)
self.setLayout(vbox)
def createHeader1a(self): #Import
HeaderBox = QGroupBox("Import Data")
inputfilebtn = QPushButton("Import")
inputfilebtn.clicked.connect(self.on_pushButtonLoad_clicked)
# importrow1
importrow1layout = QHBoxLayout()
importrow1layout.addWidget(inputfilebtn)
HeaderLayout = QVBoxLayout()
HeaderLayout.addLayout(importrow1layout)
HeaderBox.setLayout(HeaderLayout)
HeaderBox.setFlat(True)
return HeaderBox
def createHeader2a(self): #Filter
HeaderBox = QGroupBox("Filter Data")
rightlayout = QHBoxLayout()
# range slider bar to filter column data for plotting
label4 = QLabel(self)
label4.setText("Filter range:")
rightlayout.addWidget(label4)
self.slider1 = QLabeledRangeSlider(Qt.Horizontal)
self.slider1.setRange(5, 500)
self.slider1.setValue((150, 300))
rightlayout.addWidget(self.slider1)
HeaderBox.setLayout(rightlayout)
HeaderBox.setFlat(True) #
return HeaderBox
#import and return file
def getfile(self):
option = QFileDialog.Options()
fname = QFileDialog.getOpenFileName(self, 'Open file',
'c:\', "CSV files (*.csv)", options=option)
return pd.read_csv(fname[0])
@QtCore.pyqtSlot()
def on_pushButtonLoad_clicked(self):
importedfile = self.getfile()
if importedfile is None:
return
self.firstTab.MRChart(importedfile)
global database
database = importedfile
def getslider1value(self):
return self.slider1.value
class FirstTab(QWidget):
def __init__(self, data):
super(FirstTab, self).__init__()
self.data = data
self.tabwidget = TabWidget(self.data)# issue here. Attempting to # access TabWidget class
# Grid layout of entire tab
layout = QGridLayout()
layout.addWidget(self.infrastructure(self.data), 3, 0)
layout.setRowStretch(4, 3)
layout.setColumnStretch(0, 1)
self.setLayout(layout)
def MRChart(self, importedfile): # pie chart
if self.radioButton1.isChecked():
fig = go.Pie(labels=importedfile[self.radioButton1.label])
elif self.radioButton2.isChecked():
fig = go.Pie(labels=importedfile[self.radioButton2.label])
layout = go.Layout(autosize=True, legend=dict(orientation="h", xanchor='center', x=0.5))
fig = go.Figure(data=fig, layout=layout)
fig.update_layout(margin=dict(t=0, b=0, l=0, r=0))
self.browser.setHtml(fig.to_html(include_plotlyjs='cdn'))
def infrastructure(self, importedfile):
groupBox = QGroupBox("Plot")
self.browser = QtWebEngineWidgets.QWebEngineView(self)
right = QVBoxLayout()
# Change/update plot (MRChart) depending on what Radio button is selected
self.radioButton1 = QRadioButton("Label 1")
self.radioButton1.label = "Column_label_1"
self.radioButton1.toggled.connect(lambda: self.MRChart(database))
right.addWidget(self.radioButton1)
self.radioButton2 = QRadioButton("Label 2")
self.radioButton2.setChecked(True)
self.radioButton2.label = "Column_label_2"
self.radioButton2.toggled.connect(lambda: self.MRChart(database))
right.addWidget(self.radioButton2)
middleright = QHBoxLayout()
middleright.addWidget(self.browser)
middleright.addLayout(right)
groupBox.setLayout(middleright)
groupBox.setFlat(True)
print(self.tabwidget.getslider1value())# attempting to print slider value here
return groupBox
if __name__ == "__main__":
app = QApplication(sys.argv)
tabwidget = TabWidget(data=None)
tabwidget.show()
app.exec()
递归错误很明显:TabWidget
尝试创建 FirstTab
,但您正在尝试创建 另一个 TabWidget
,这将创建进一步的 FirstTab
等等。
如果你想保持对象之间的引用,你必须传递引用,而不是创建新的实例(见下面的注释)。
此外,由于 FirstTab
在 __init__
中调用了 infrastructure
,此时父窗口小部件中的滑块尚未创建。
您必须在创建滑块后移动FirstTab
的创建,并在构造函数中传递引用。
class TabWidget(QDialog):
def __init__(self, data):
super(TabWidget, self).__init__()
self.data = data
self.showMaximized()
# create Header
FilterLayout = QHBoxLayout()
FilterLayout.addWidget(self.createHeader1a(), 1)
FilterLayout.addWidget(self.createHeader2a(), 4)
self.firstTab = FirstTab(self) # <- pass the reference of the parent
# ...
class FirstTab(QWidget):
def __init__(self, tabwidget):
super(FirstTab, self).__init__()
self.tabwidget = tabwidget
self.data = tabwidget.data
# ...
请注意,这与您在上一个问题中遇到的相同问题。我强烈建议您复习一下 类 和实例以及 OOP 的基础知识,因为对这些方面的知识和理解不容忽视。
我正在开发一个用于导入和绘制数据(csv 文件)的 GUI。数据最初使用 getfile()
和 on_pushButtonLoad_clicked()
在 TabWidget()
class 中导入,然后传递到 FirstTab()
class,其中 MRChart()
是绘制在 infrastructure()
小部件中。为此,我在 TabWidget()
中创建了 firstTab
实例(如果我的术语在这里不正确,请见谅)。
最终目标是根据在范围滑块上选择的数值范围更新绘图。首先,我想将 slider1
的值传递给 FirstTab()
,我应该可以从那里进行管理。为此,我尝试在 FirstTab()
中创建 tabwidget
实例。但是,我得到以下信息:“RecursionError:超出最大递归深度”。我认为这是由于每个 class 都有一个自己的实例包含在另一个中。
感谢任何帮助。
代码:
class TabWidget(QDialog):
def __init__(self, data):
super(TabWidget, self).__init__()
self.data = data
self.firstTab = FirstTab(self.data)
self.showMaximized()
# create Header
FilterLayout = QHBoxLayout()
FilterLayout.addWidget(self.createHeader1a(), 1)
FilterLayout.addWidget(self.createHeader2a(), 4)
# create Tab
tabwidget = QTabWidget()
tabwidget.addTab(self.firstTab, "Tab 1")
vbox = QVBoxLayout()
vbox.addLayout(FilterLayout)
vbox.addWidget(tabwidget)
self.setLayout(vbox)
def createHeader1a(self): #Import
HeaderBox = QGroupBox("Import Data")
inputfilebtn = QPushButton("Import")
inputfilebtn.clicked.connect(self.on_pushButtonLoad_clicked)
# importrow1
importrow1layout = QHBoxLayout()
importrow1layout.addWidget(inputfilebtn)
HeaderLayout = QVBoxLayout()
HeaderLayout.addLayout(importrow1layout)
HeaderBox.setLayout(HeaderLayout)
HeaderBox.setFlat(True)
return HeaderBox
def createHeader2a(self): #Filter
HeaderBox = QGroupBox("Filter Data")
rightlayout = QHBoxLayout()
# range slider bar to filter column data for plotting
label4 = QLabel(self)
label4.setText("Filter range:")
rightlayout.addWidget(label4)
self.slider1 = QLabeledRangeSlider(Qt.Horizontal)
self.slider1.setRange(5, 500)
self.slider1.setValue((150, 300))
rightlayout.addWidget(self.slider1)
HeaderBox.setLayout(rightlayout)
HeaderBox.setFlat(True) #
return HeaderBox
#import and return file
def getfile(self):
option = QFileDialog.Options()
fname = QFileDialog.getOpenFileName(self, 'Open file',
'c:\', "CSV files (*.csv)", options=option)
return pd.read_csv(fname[0])
@QtCore.pyqtSlot()
def on_pushButtonLoad_clicked(self):
importedfile = self.getfile()
if importedfile is None:
return
self.firstTab.MRChart(importedfile)
global database
database = importedfile
def getslider1value(self):
return self.slider1.value
class FirstTab(QWidget):
def __init__(self, data):
super(FirstTab, self).__init__()
self.data = data
self.tabwidget = TabWidget(self.data)# issue here. Attempting to # access TabWidget class
# Grid layout of entire tab
layout = QGridLayout()
layout.addWidget(self.infrastructure(self.data), 3, 0)
layout.setRowStretch(4, 3)
layout.setColumnStretch(0, 1)
self.setLayout(layout)
def MRChart(self, importedfile): # pie chart
if self.radioButton1.isChecked():
fig = go.Pie(labels=importedfile[self.radioButton1.label])
elif self.radioButton2.isChecked():
fig = go.Pie(labels=importedfile[self.radioButton2.label])
layout = go.Layout(autosize=True, legend=dict(orientation="h", xanchor='center', x=0.5))
fig = go.Figure(data=fig, layout=layout)
fig.update_layout(margin=dict(t=0, b=0, l=0, r=0))
self.browser.setHtml(fig.to_html(include_plotlyjs='cdn'))
def infrastructure(self, importedfile):
groupBox = QGroupBox("Plot")
self.browser = QtWebEngineWidgets.QWebEngineView(self)
right = QVBoxLayout()
# Change/update plot (MRChart) depending on what Radio button is selected
self.radioButton1 = QRadioButton("Label 1")
self.radioButton1.label = "Column_label_1"
self.radioButton1.toggled.connect(lambda: self.MRChart(database))
right.addWidget(self.radioButton1)
self.radioButton2 = QRadioButton("Label 2")
self.radioButton2.setChecked(True)
self.radioButton2.label = "Column_label_2"
self.radioButton2.toggled.connect(lambda: self.MRChart(database))
right.addWidget(self.radioButton2)
middleright = QHBoxLayout()
middleright.addWidget(self.browser)
middleright.addLayout(right)
groupBox.setLayout(middleright)
groupBox.setFlat(True)
print(self.tabwidget.getslider1value())# attempting to print slider value here
return groupBox
if __name__ == "__main__":
app = QApplication(sys.argv)
tabwidget = TabWidget(data=None)
tabwidget.show()
app.exec()
递归错误很明显:TabWidget
尝试创建 FirstTab
,但您正在尝试创建 另一个 TabWidget
,这将创建进一步的 FirstTab
等等。
如果你想保持对象之间的引用,你必须传递引用,而不是创建新的实例(见下面的注释)。
此外,由于 FirstTab
在 __init__
中调用了 infrastructure
,此时父窗口小部件中的滑块尚未创建。
您必须在创建滑块后移动FirstTab
的创建,并在构造函数中传递引用。
class TabWidget(QDialog):
def __init__(self, data):
super(TabWidget, self).__init__()
self.data = data
self.showMaximized()
# create Header
FilterLayout = QHBoxLayout()
FilterLayout.addWidget(self.createHeader1a(), 1)
FilterLayout.addWidget(self.createHeader2a(), 4)
self.firstTab = FirstTab(self) # <- pass the reference of the parent
# ...
class FirstTab(QWidget):
def __init__(self, tabwidget):
super(FirstTab, self).__init__()
self.tabwidget = tabwidget
self.data = tabwidget.data
# ...
请注意,这与您在上一个问题中遇到的相同问题。我强烈建议您复习一下 类 和实例以及 OOP 的基础知识,因为对这些方面的知识和理解不容忽视。