Search code examples
pythonmultithreadingpyqt5pyqtgraph

Is it possible to get an array from a thread in PyQt5?


I have created a code that take the signal from a oscilloscope and plot in real time in pyqtGraph inside a GUI, but its locking. I'm trying to use Qthread to unlock the GUI, but i am an amateur programmer and i don't know if it is the right way.

So i take this code to keep trying without the oscilloscope and i'm trying to make the calculation in a thread and keep the GUI running, but i'm stuck. Is there a way to get the array self.s and make a real time plot without locking the GUI?

import pyqtgraph as pg
import numpy as np
import time
import sys
from PyQt5 import QtGui
from PyQt5.QtWidgets import *
from PyQt5.QtCore import QThread, pyqtSignal


class plotarT(QThread):
    signal = pyqtSignal('PyQt_PyObject')

    def __init__(self):
        QThread.__init__(self)

    def __del__(self):
        self.wait()

    def update(self):
        self.phase = 0
        self.t = np.arange(0, 3.0, 0.01)
        self.s = np.sin(2 * np.pi * self.t + self.phase) #Sin function
        self.phase += 0.1
        time.sleep(2) #To simulate the time that oscilloscope take to respond


    def run(self):
        self.update()
        self.signal.emit('QObject')


class Window(QDialog):
    def __init__(self):
        self.app = QtGui.QApplication(sys.argv)
       super().__init__()
        self.title = "PyQt5 GridLayout"
        self.top = 100
        self.left = 100
        self.width = 1000
        self.height = 600
        self.InitWindow()
        self.traces = dict()
        pg.setConfigOptions(antialias=True)

    def InitWindow(self):
        self.setWindowIcon(QtGui.QIcon("icon.png"))
        self.setWindowTitle(self.title)
        self.setGeometry(self.top, self.left, self.width, self.height)

        self.gridLayoutCreation()
        vboxLayout = QVBoxLayout()
        vboxLayout.addWidget(self.groupBox)
        self.setLayout(vboxLayout)

        self.show()

    def gridLayoutCreation(self): 
        self.groupBox = QGroupBox("Grid Layout Example")

        gridLayout = QGridLayout()
        self.guiplot = pg.PlotWidget()
        gridLayout.addWidget(self.guiplot,0,8,8,12)
        self.groupBox.setLayout(gridLayout)

        gridLayout.addWidget(QLabel('Tempo'), 0,0)
        self.time = QLineEdit('')
        gridLayout.addWidget(self.time, 1,0)


    def plotar(self):
        self.guiplot.clear()
        self.guiplot.plot(s)
        #self.guiplot.plot(c)

    def teste(self):
        self.get_thread = plotarT()
        self.get_thread.start()



def main():
    app = QtGui.QApplication(sys.argv)
    form = Window()
    form.show()
    form.teste()
    app.exec_()

if __name__ == '__main__':
    main()

Solution

  • Try it:

    import pyqtgraph as pg
    import numpy as np
    #import time
    import sys
    from PyQt5 import QtGui
    from PyQt5.QtWidgets import *
    from PyQt5.QtCore import QThread, pyqtSignal
    
    
    class plotarT(QThread):
    
        signal = pyqtSignal(object)                             # object
    
        def __init__(self, parent=None):
            super().__init__()
            self.s  = None                                      # +++
            self.phase = 0                                      # +++
    
        def __del__(self):
            self.wait()
    
        def update(self):
    #        self.phase = 0                                     # --- 
            self.t = np.arange(0, 3.0, 0.01)
            self.s = np.sin(2 * np.pi * self.t + self.phase)    # Sin function
            self.phase += 0.1
            QThread.msleep(200)    # time.sleep(0.2) 
    
    
        def run(self):
            for i in range(100):                                # +++ Some cycle
                self.update()
                self.signal.emit(self.s)                        # self.s
    
    
    class Window(QDialog):
        def __init__(self):
    #        self.app = QtGui.QApplication(sys.argv)
            super().__init__()
            self.title = "PyQt5 GridLayout"
            self.top = 100
            self.left = 100
            self.width = 1000
            self.height = 600
            self.InitWindow()
    
            self.traces = dict()
            pg.setConfigOptions(antialias=True)
    
        def InitWindow(self):
            self.setWindowIcon(QtGui.QIcon("icon.png"))
            self.setWindowTitle(self.title)
            self.setGeometry(self.top, self.left, self.width, self.height)
    
            self.gridLayoutCreation()
    
            vboxLayout = QVBoxLayout()
            vboxLayout.addWidget(self.groupBox)
            self.setLayout(vboxLayout)
    
            self.show()
    
        def gridLayoutCreation(self): 
            self.groupBox = QGroupBox("Grid Layout Example")
    
            gridLayout   = QGridLayout()
            self.guiplot = pg.PlotWidget()
            gridLayout.addWidget(self.guiplot,0,8,8,12)
            self.groupBox.setLayout(gridLayout)
    
            gridLayout.addWidget(QLabel('Tempo'), 0,0)
            self.timeEdit = QLineEdit('')                       # time <-> timeEdit
            gridLayout.addWidget(self.timeEdit, 1,0)            # time <-> timeEdit
    
    
        def plotar(self, s):                                    
            self.guiplot.clear()
            self.guiplot.plot(s)
            #self.guiplot.plot(c)
    
        def teste(self):
            self.get_thread = plotarT()
            self.get_thread.signal.connect(self.displayS)        # <--- +++
            self.get_thread.start()
    
        def displayS(self, self_s):                              # <--- +++
            """ Here is your `self.s` array. 
                Draw a graph in real time without blocking the graphical interface.
            """
    #        print("\n Here is your `self.s` array. \n", self_s)
    
            self.plotar(self_s)
    
    
    def main():
        app = QApplication(sys.argv)  # QtGui.
        form = Window()
        form.show()
        form.teste()
        app.exec_()
    
    if __name__ == '__main__':
        main()
    

    enter image description here