2

I am TRYING to make an app where I want to have several PlotWidgets that plot the signal from up to 5 sensors I've got in my Arduino. As soon as I have two updating plots, the GUI does not respond, and I need to pause/restart the plotting, and popping up alerts for some values. To solve that, I have started researching in order to use QThread, but that might be impossible with PyQtGraph, since we cannot have plotting done in multiple threads? My code for two PlotWidgets looks like:

from PyQt4 import QtCore, QtGui
import pyqtgraph as pg
import random
import sys

class MainWindow(QtGui.QWidget):
   def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        layout = QtGui.QHBoxLayout()
        self.button = QtGui.QPushButton('Start Plotting Left')
        layout.addWidget(self.button)
        self.button.clicked.connect(self.plotter)
        self.button2 = QtGui.QPushButton('Start Plotting Right')
        layout.addWidget(self.button2)
        self.button2.clicked.connect(self.plotter2)
        self.plot = pg.PlotWidget()
        layout.addWidget(self.plot)
        self.plot2 = pg.PlotWidget()
        layout.addWidget(self.plot2)
        self.setLayout(layout)


    def plotter(self):
        self.data =[0]
        self.curve = self.plot.getPlotItem().plot()

        self.timer = QtCore.QTimer()
        self.timer.timeout.connect(self.updater)
        self.timer.start(0)

    def updater(self):
        self.data.append(self.data[-1]+0.2*(0.5-random.random()) )
        self.curve.setData(self.data)#Downsampling does not help

   def plotter2(self):
        self.data2 =[0]
        self.curve2 = self.plot2.getPlotItem().plot()

        self.timer = QtCore.QTimer()
        self.timer.timeout.connect(self.updater2)
        self.timer.start(0)

    def updater2(self):
        self.data2.append(self.data[-1]+0.2*(0.5-random.random()) )
        self.curve2.setData(self.data) #Downsampling does not help



if __name__ == '__main__':
    app = QtGui.QApplication([])
    window = MainWindow()
    window.show()
    app.exec_()

I am ready to read and try a lot from QThread, but first I need to know if it's possible, or if I am wasting my days and sleep. Does anybody have a hint of how could I get it to work?

Ivy
  • 175
  • 2
  • 14

1 Answers1

2

Your code has a couple of typographical errors that stops it from working

Inside updater2 you are using self.data instead of self.data2. The code should be:

def updater2(self):
    self.data2.append(self.data2[-1]+0.2*(0.5-random.random()) )
    self.curve2.setData(self.data2) #Downsampling does not help

Also, when creating your second timer, you store it in the same variable as the first timer, which causes it to stop. The corrected code should read:

def plotter2(self):
    self.data2 =[0]
    self.curve2 = self.plot2.getPlotItem().plot()

    self.timer2 = QtCore.QTimer()
    self.timer2.timeout.connect(self.updater2)
    self.timer2.start(0)

Note that "starting" a timer after it is already started (aka clicking the same button twice) causes the program to crash for me. You should probably disable the buttons, or have a second click stop the timer or something. It is up to you.

In regards to threading, you may see some performance gain from threading by reading the data in from the arduino over serial in another thread (the GUI won't lock up), but you will need to send the data via a PyQt signal to the main thread and run the plotting command there. There are many examples on StackOverflow on how to thread properly with PyQt (for instance here)

Graham
  • 7,431
  • 18
  • 59
  • 84
three_pineapples
  • 11,579
  • 5
  • 38
  • 75