Pavel.D
Pavel.D

Reputation: 581

PyQt5 Matplotlib dataplot with signal and slot with lists

I have 3 classes, mainwindow class, plot class and Listxy class. I want to connect X and Y lists in class Listxy to class Plot in order to draw data . I want to connect them in mainwindow class and class plot would update according to X and Y lists. i.e. x = [x for x in X] and y = [y for y in Y]. I am not really sure, that slot and signal would work with lists. I need help on that.

Visualization:

enter image description here

The code:

import sys
from PyQt5 import QtCore, QtWidgets, QtGui
import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar

class Mainwindow(QtWidgets.QMainWindow):
    def __init__(self):
        super(Mainwindow, self).__init__()

        self.setMinimumSize(QtCore.QSize(1200,800))
        self.setWindowTitle('My Graphic Window')

        self.list_x_y = Listxy()
        self.plotview = Plot()
        self.setCentralWidget(self.plotview)


class Plot(QtWidgets.QWidget):
    def __init__(self):
        super(Plot, self).__init__()
        self.initializewidget()
        self.plot1()

    def initializewidget(self):
        self.setWindowTitle("Plotting M&N")
        gridlayout = QtWidgets.QGridLayout()
        self.setLayout(gridlayout)

        self.figure = plt.figure(figsize=(15,5))
        self.canvas = FigureCanvas(self.figure)
        self.toolbar = NavigationToolbar(self.canvas,self)
        gridlayout.addWidget(self.canvas,1,0,1,2)
        gridlayout.addWidget(self.toolbar,0,0,1,2)


    def plot1(self):
        ax = self.figure.add_subplot(111)
        x = [i for i in range(100)]
        y = [i**2 for i in x]
#        x = [0]
#        y = [0]
        ax.plot(x,y, 'y.-')
        ax.set_title('Quadratic Plot')
        self.canvas.draw()


class Listxy:

    X = []
    Y = []

    def createdata(self):
        for x in range(0,100):
            X.append(x)
        for y in range(0,100):
            Y.append(y) 

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    im = Mainwindow()
    im.show()
    sys.exit(app.exec_())

Upvotes: 1

Views: 668

Answers (1)

eyllanesc
eyllanesc

Reputation: 243983

The signals and slots support all types of python data so lists can be used. Also keep in mind that only the classes that inherit from QObject can have signals. The following example shows random data updating the plot every 100 ms.

import sys
import random
from PyQt5 import QtCore, QtWidgets, QtGui
import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar

class Mainwindow(QtWidgets.QMainWindow):
    def __init__(self):
        super(Mainwindow, self).__init__()

        self.setMinimumSize(QtCore.QSize(1200,800))
        self.setWindowTitle('My Graphic Window')

        self.list_x_y = ListXY()
        self.plotview = Plot()
        self.setCentralWidget(self.plotview)
        self.list_x_y.listChanged.connect(self.plotview.update_data)

        timer = QtCore.QTimer(self, interval=100)
        timer.timeout.connect(self.list_x_y.createdata)
        timer.start()

class Plot(QtWidgets.QWidget):
    def __init__(self):
        super(Plot, self).__init__()
        self.initializewidget()

    def initializewidget(self):
        self.setWindowTitle("Plotting M&N")
        gridlayout = QtWidgets.QGridLayout()
        self.setLayout(gridlayout)

        self.figure = plt.figure(figsize=(15,5))
        self.canvas = FigureCanvas(self.figure)
        self.toolbar = NavigationToolbar(self.canvas,self)
        gridlayout.addWidget(self.canvas,1,0,1,2)
        gridlayout.addWidget(self.toolbar,0,0,1,2)

        self._ax = self.figure.add_subplot(111)
        self._ax.set_title('Random Plot')
        self._line = self._ax.plot([], [], 'y.-')[0]

    @QtCore.pyqtSlot(list, list)
    def update_data(self, x, y):
        self._line.set_data(x, y)
        self._ax.set_xlim(min(x), max(x))
        self._ax.set_ylim(min(y), max(y))
        self.canvas.draw()

class ListXY(QtCore.QObject):
    listChanged = QtCore.pyqtSignal(list, list)

    def createdata(self):
        X, Y = list(range(100)), []
        for y in range(0,100):
            Y.append(random.randint(0, 100)) 
        self.listChanged.emit(X, Y)

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    im = Mainwindow()
    im.show()
    sys.exit(app.exec_())

enter image description here

Upvotes: 2

Related Questions