Search code examples
pythonmatplotlibpyqt5signals-slots

How to implement a QPushbutton to emit pyqt signal and call another class?


I'm trying to learn the basic usage of emitting/receiving signals and I'm running into some trouble.

I wanted to start with something basic so I created a MainWindow and put a QPushButton called "plot".

When the button is pushed it takes the arguments (self, xdata, ydata) and runs the method initiatePlot from my class MainWindow(QMainWindow)

    self.plotbtn = QPushButton("Plot")
    self.plotbtn.clicked.connect(partial(self.initiatePlot, xdata, ydata))

    def initiatePlot(self,x,y):
        PlotSignal = pyqtSignal(list, list)
        self.PlotSignal.emit(x, y)

Afterwards I tried to connect it to my plotter class, but I just get "Process finished exit code 1" I believe the error to be coming from this particular line of code in my below class.

self.PlotSignal.connect(self.plotData)

CODE FOR PLOTTER CLASS

class createFIG(FigureCanvas):
  def __init__(self):
    #super().__init__(Figure(tight_layout=True))
    self.figure = plt.figure()
    self.axes = self.figure.add_subplot(111)

    self.name = ""

    # xdata = [1,2,3,4,5]
    # ydata = [12,4,56,78,9]

    plt.figure()
    self.axes.set_xlabel('x label')

    #self.plotData(xdata,ydata)

    self.PlotSignal.connect(self.plotData)


  def plotData(self, xdata,ydata):
    print("plotting")
    self.axes.plot(xdata, ydata)
    self.draw()
    plt.show()

Sorry the whitespace might be a little messed up.

The current issue is how I go about receiving the signal I emit from my initiatePlot method.

The end goals is to be able to click the plot button and create a new window with a new plot figure each time.

If there is an easier way to link the button in my mainwindow to plotting class that would be helpful.

Here is a link to my full code: https://github.com/Silvuurleaf/InteractiveGraphing/blob/master/LiveGraphing.py


Solution

  • As said, I'm not sure if this is really what you are looking for, but the following code should create a new matplotlib window, each time the button is pressed.

    import sys
    #Importing PyQt5 library to construct widgets for Graphic User Interface (GUI) application
    from PyQt5 import QtCore, QtGui, QtWidgets
    from PyQt5.QtGui import (QLineEdit, QPushButton, QSlider, QApplication, QVBoxLayout, QHBoxLayout,
                                 QWidget, QLabel, QCheckBox, QRadioButton, QPlainTextEdit, QSizePolicy,
                                 QMainWindow,QFrame, QFileDialog, QTableWidgetItem, QTableWidget, QMenu, QMessageBox,
                                 QAction, QToolBar)
    from PyQt5.QtCore import Qt, QAbstractTableModel, pyqtSignal
    
    from functools import partial
    import matplotlib
    matplotlib.use("Qt5Agg")
    
    from matplotlib import pyplot as plt
    plt.style.use(['ggplot'])
    
    class createFIG():
        def __init__(self):
            self.figure = plt.figure()
            self.axes = self.figure.add_subplot(111)
            self.name = ""
            self.axes.set_xlabel('x label')
    
        def plotData(self, xdata,ydata):
            print("plotting")
            self.axes.plot(xdata, ydata)
            plt.show()
    
    
    class MainWindow(QMainWindow):
        def __init__(self):
            super(MainWindow, self).__init__()
            self.setWindowTitle("Perspective")
    
            self.initializeUI()
    
        def initializeUI(self):
    
            xdata = [1,2,3,4,5]
            ydata = [12,4,56,78,9]
    
            #Main Widget
            self.main_widget = QWidget(self)
            self.setCentralWidget(self.main_widget)
    
            self.plotbtn = QPushButton("Plot")
            self.plotbtn.clicked.connect(partial(self.initiatePlot, xdata, ydata))
    
            self.hMAIN = QHBoxLayout(self.main_widget)
            self.vboxLeft = QVBoxLayout()
            self.vboxLeft.addWidget(self.plotbtn)
    
            self.hbox1 = QHBoxLayout()
    
            self.vboxLeft.addLayout(self.hbox1)
    
            self.PlotLayout = QVBoxLayout()
    
            self.hMAIN.addLayout(self.vboxLeft)
            self.hMAIN.addLayout(self.PlotLayout)
    
            self.show()
    
        def initiatePlot(self,x,y):
            print("emit signal")
            f = createFIG()
            f.plotData(x, y)
    
    
    def main():
            # main loop
            app = QApplication(sys.argv)
            # instance
            window = MainWindow()
            window.show()
            # appWindow = MainWindow()
            sys.exit(app.exec_())
    
    if __name__ == "__main__":
        main()