Updating n PlotWidgets in PyQt4 for Live Plotting

615 views
Skip to first unread message

Ivan Yélamos Vela

unread,
Jan 19, 2017, 8:54:18 AM1/19/17
to pyqtgraph
Hello,

First of all thanks for creating PyQtGraph.I have been working pretty hard before daring asking here. 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 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 everything about QThread, but first I need to know if it's possible, or if I am wasting my life and sleep.

Should I give up my hopes of achieving a responsive GUI by using the plot().setdata() method? And perhaps just doing the data appending in a worker thread and redrawing the plots everytime?

Is there any technology that can do plotting in different threads? 

Any help or suggestion am I going to work hard on! :-)

Cheers from the island of Mallorca

Ivan Yélamos Vela

unread,
Jan 20, 2017, 7:46:53 AM1/20/17
to pyqtgraph
Hello guys (specially Luke I can see):

don't use your time trying to look at the previous code, since I nice help from a charitable soul on Stack Overflow!:

import random
import sys

import pyqtgraph as pg
import time
from PyQt4 import QtGui, QtCore


class MyThread(QtCore.QThread):
   
def __init__(self, curve, parent=None):
       
super(MyThread, self).__init__(parent=parent)
       
self.curve = curve
       
self.data = [0]

   
def run(self):
       
while True:
           
self.data.append(self.data[-1] + 0.2 * (0.5 - random.random()))
           
self.curve.setData(self.data, downsample=10)
            time
.sleep(0.1)
           
print(len(self.data))


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

   
def plotter(self):
       
self.curve = self.plot.getPlotItem().plot()
        myThread
= MyThread(self.curve, self)
        myThread
.start()


class MainWindow(QtGui.QMainWindow):

   
def __init__(self, parent=None):
       
super(MainWindow, self).__init__(parent)

       
self.centralwidget = QtGui.QWidget(self)
       
self.setCentralWidget(self.centralwidget)
       
self.horizontalLayout = QtGui.QHBoxLayout(self.centralwidget)
       
self.login_widget_1 = LoginWidget(self)
       
self.horizontalLayout.addWidget(self.login_widget_1)

       
self.login_widget_2 = LoginWidget(self)
       
self.horizontalLayout.addWidget(self.login_widget_2)

       
self.setCentralWidget(self.centralwidget)

if __name__ == '__main__':
    app
= QtGui.QApplication(sys.argv)
    w
= MainWindow()
    w
.show()
    sys
.exit(app.exec_())



And surprise, the GUI is responsive! :-) The only downside is that I need to maximize/minimize in order for the plots to update? I'm working on that...

Ivan Yélamos Vela

unread,
Jan 25, 2017, 5:25:47 AM1/25/17
to pyqtgraph
Allright guys, it seems like I got it, again through a sweet dude on StackOverflow:

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


class MyThread(QtCore.QThread):

    signal
= QtCore.pyqtSignal(object)
   
def __init__(self, parent=None):
       
super(MyThread, self).__init__(parent=parent)
       
self.data = [0]

   
def __del__(self):
       
self.exiting = True
       
self.wait()

   
def run(self):
       
while True:
           
self.data.append(random.random())
           
self.signal.emit(self.data)
            time
.sleep(0.1)



class LoginWidget(QtGui.QWidget):
   
def __init__(self, parent=None):
       
super(LoginWidget, self).__init__(parent)

       
self.myThread = MyThread()
        layout
= QtGui.QHBoxLayout()

       
self.button = QtGui.QPushButton('Start Plotting')
        layout
.addWidget(self.button)
       
self.plot = pg.PlotWidget()
        layout
.addWidget(self.plot)
       
self.setLayout(layout)

       
self.curve = self.plot.getPlotItem().plot()
       
self.button.clicked.connect(self.start)


   
def plotter(self, data):
       
self.curve.setData(data)

   
def start(self):
       
self.myThread.start()
       
self.myThread.signal.connect(self.plotter)


class MainWindow(QtGui.QMainWindow):

   
def __init__(self, parent=None):
       
super(MainWindow, self).__init__(parent)

       
self.centralwidget = QtGui.QWidget(self)
       
self.setCentralWidget(self.centralwidget)
       
self.horizontalLayout = QtGui.QHBoxLayout(self.centralwidget)
       
self.login_widget_1 = LoginWidget(self)
       
self.horizontalLayout.addWidget(self.login_widget_1)
       
self.login_widget_2 = LoginWidget(self)
       
self.horizontalLayout.addWidget(self.login_widget_2)
       
self.setCentralWidget(self.centralwidget)


if __name__ == '__main__':

    app
= QtGui.QApplication(sys.argv)
    w
= MainWindow()
    w
.show()
    sys
.exit(app.exec_())

Thanks for being there!
Reply all
Reply to author
Forward
0 new messages