在 PyQt5 的不同 class 中按下按钮时如何更新图形?

How can I update a figure when button is pressed in a different class in PyQt5?

我正在使用 PyQt5 在 python 中构建一个 GUI。使用位于 TabWidget.

on_pushButtonLoad_clicked()get_file() 导入数据

我的目标是:

  1. 将此数据(导入的文件)传输到 FirstTab()
  2. 使用最近导入的数据更新绘图MRChart(importedfile)

我已经完成了将数据传输到 FirstTab() 的第一个目标,由此生成了绘图并可以使用 fig.show() 在浏览器中显示(出于演示目的)。虽然 MRChart(importedfile) 通过 self.browser 连接到绘图小部件 energy(),但图形无法在 GUI 中显示。

代码:

class TabWidget(QDialog):
    def __init__(self, data):
        super(TabWidget, self).__init__()
        self.data = data

        self.showMaximized()

        #create filter object
        FilterLayout = QHBoxLayout()
        FilterLayout.addWidget(self.createHeader1a(), 2)#column width

        #create tab widget object
        tabwidget = QTabWidget()
        tabwidget.addTab(FirstTab(self.data), "Tab 1")

        vbox = QVBoxLayout()
        vbox.addLayout(FilterLayout)
        vbox.addWidget(tabwidget)

        self.setLayout(vbox)

    def createHeader1a(self): # function defining characteristics of each group/grid object
        HeaderBox = QGroupBox("Import Data")

        inputfilebtn = QPushButton("Import")
        inputfilebtn.resize(150, 50)
        inputfilebtn.clicked.connect(self.on_pushButtonLoad_clicked)

        #importrow1
        importrow1layout = QHBoxLayout()
        importrow1layout.addWidget(inputfilebtn)
        importrow1layout.addStretch()

        HeaderLayout = QGridLayout()
        HeaderLayout.addLayout(importrow1layout, 0, 1)
        HeaderBox.setLayout(HeaderLayout)
        HeaderBox.setFlat(True)

        return HeaderBox

    def getfile(self):
        option = QFileDialog.Options()
        fname = QFileDialog.getOpenFileName(self, 'Open file',
                                            'c:\', "CSV files (*.csv)", options=option)

        global importedfile
        importedfile = pd.read_csv(fname[0])

    @QtCore.pyqtSlot()
    def on_pushButtonLoad_clicked(self):
        self.getfile()
        FT=FirstTab(data=importedfile)
        FT.MRChart(importedfile)

class FirstTab(QWidget):
    def __init__(self, data):
        super(FirstTab, self).__init__() 
        self.data = data

        # Grid layout of entire tab
        layout = QGridLayout()
        layout.addWidget(self.energy(), 3, 0)
        layout.setRowStretch(3, 3)
        layout.setColumnStretch(0, 1)

        self.setLayout(layout)


    def MRChart(self, importedfile): # pie
        fig = go.Pie(labels=importedfile["Label1"], values=importedfile["Label2"])
        layout = go.Layout(autosize=True, legend=dict(orientation="h",xanchor='center', x=0.5))# height = 600, width = 1000,
        fig = go.Figure(data=fig, layout=layout)
        fig.update_layout(margin=dict(t=0, b=0, l=0, r=0))
        fig.show()# only included to prove that figure has been created
        self.browser.setHtml(fig.to_html(include_plotlyjs='cdn'))


    def energy(self):
        groupBox = QGroupBox("Box Title")

        self.browser = QtWebEngineWidgets.QWebEngineView(self)
        exportfilebtn = QCheckBox("tickbox1")
        middleright = QHBoxLayout()
        middleright.addWidget(self.browser)
        middleright.addWidget(exportfilebtn)
        groupBox.setLayout(middleright)
        groupBox.setFlat(True)

        return groupBox

if __name__ == "__main__":
    app = QApplication(sys.argv)
    tabwidget = TabWidget(data=None)
    tabwidget.show()
    app.exec()

根据 musicamante 的回答更新了代码

class TabWidget(QDialog):
    def __init__(self, data):
        super(TabWidget, self).__init__()
        self.data = data
        self.firstTab = FirstTab(self.data)

        #create filter object
        FilterLayout = QHBoxLayout()
        FilterLayout.addWidget(self.createHeader1a(), 2)#column width

        #create tab widget object
        tabwidget = QTabWidget()
        tabwidget.addTab(self.firstTab "Tab 1")

        vbox = QVBoxLayout()
        vbox.addLayout(FilterLayout)
        vbox.addWidget(tabwidget)

        self.setLayout(vbox)

    def createHeader1a(self): # function defining characteristics of each group/grid object
        HeaderBox = QGroupBox("Import Data")

        inputfilebtn = QPushButton("Import")
        inputfilebtn.resize(150, 50)
        inputfilebtn.clicked.connect(self.on_pushButtonLoad_clicked)

        #importrow1
        importrow1layout = QHBoxLayout()
        importrow1layout.addWidget(inputfilebtn)
        importrow1layout.addStretch()

        HeaderLayout = QGridLayout()
        HeaderLayout.addLayout(importrow1layout, 0, 1)
        HeaderBox.setLayout(HeaderLayout)
        HeaderBox.setFlat(True)

        return HeaderBox

    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)



class FirstTab(QWidget):
    def __init__(self, data):
        super(FirstTab, self).__init__() 
        self.data = data

        # Grid layout of entire tab
        layout = QGridLayout()
        layout.addWidget(self.energy(), 3, 0)
        layout.setRowStretch(3, 3)
        layout.setColumnStretch(0, 1)

        self.setLayout(layout)


    def MRChart(self, importedfile): # pie
        fig = go.Pie(labels=importedfile["Label1"], values=importedfile["Label2"])
        layout = go.Layout(autosize=True, legend=dict(orientation="h",xanchor='center', x=0.5))# height = 600, width = 1000,
        fig = go.Figure(data=fig, layout=layout)
        fig.update_layout(margin=dict(t=0, b=0, l=0, r=0))
        fig.show()# only included to provde figure is created
        self.browser.setHtml(fig.to_html(include_plotlyjs='cdn'))


    def energy(self):
        groupBox = QGroupBox("Box Title")

        self.browser = QtWebEngineWidgets.QWebEngineView(self)
        exportfilebtn = QCheckBox("tickbox1")
        middleright = QHBoxLayout()
        middleright.addWidget(self.browser)
        middleright.addWidget(exportfilebtn)
        groupBox.setLayout(middleright)
        groupBox.setFlat(True)

        return groupBox

if __name__ == "__main__":
    app = QApplication(sys.argv)
    tabwidget = TabWidget(data=None)
    tabwidget.show()
    app.exec()

您正在创建 FirstTab 的新实例,而不是使用现有实例。

您必须保留对第一个实例的引用,然后调用 它的 MRChart 函数。

另外,你应该使用全局变量:getfile()应该return值,你应该在 on_pushButtonLoad_clicked.

中使用 returned 值
class TabWidget(QDialog):
    def __init__(self, data):
        # ...
        self.firstTab = FirstTab(self.data)
        tabwidget.addTab(self.firstTab, "Tab 1")
        # ...

    def getfile(self):
        option = QFileDialog.Options()
        fname, _ = QFileDialog.getOpenFileName(self, 'Open file',
                                            'c:\', "CSV files (*.csv)", options=option)

        if fname:
            return pd.read_csv(fname)

    @QtCore.pyqtSlot()
    def on_pushButtonLoad_clicked(self):
        importedfile = self.getfile()
        if importedfile is None:
            return
        self.firstTab.MRChart(importedfile)

请注意,在 添加其元素后仅 显示 window 是一种很好的做法,而且 通常也更好不__init__ 调用show*()。在添加到布局的小部件上使用 resize() 也毫无意义。