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

Issue

I am building a GUI in python using PyQt5. Data is imported using on_pushButtonLoad_clicked() and get_file() located in TabWidget.

My goal is to:

  1. transfer this data (importedfile) to FirstTab()
  2. update the plot MRChart(importedfile) using the recently imported data.

I have completed the first goal in transferring the data to FirstTab() whereby the plot is generated and can be shown (for demonstrative purposes) in the browser using fig.show(). Although MRChart(importedfile) is connected to the plotting widget energy() by self.browser, the figure fails to show in the GUI.

Code:

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()

Updated code in line with musicamante’s answer

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()

Solution

You’re creating a new instance of FirstTab, instead of using the existing one.

You must keep a reference to the first instance and then call its MRChart function.

Also, you should not use globals: getfile() should return the value, and you should use that returned value in on_pushButtonLoad_clicked.

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)

Note that it’s good practice to show the window only after adding its elements, and it’s also usually better to not call show*() in the __init__. It’s also pointless to use resize() on a widget that is being added to a layout.

Answered By – musicamante

Answer Checked By – Mary Flores (BugsFixing Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *