So it looks like updating the plot data from an outside thread is just a 
Bad Idea. Here is the same example wrapping the callback in a Qt 
Signal/Slot pattern. Note that signals need to be defined inside a QObject, 
hence the explicit instantiation of a GraphicsLayoutWidget. So far it seems 
to work as expected.

import numpy as np
from PyQt5 import QtWidgets
from PyQt5.QtCore import pyqtSignal, pyqtSlot
import pyqtgraph as pg
from pyqtgraph.Qt import QtCore, QtGui
from pyqtgraph import GraphicsLayoutWidget
from threading import Thread, Event
import time

# Routine to acquire and serve data
# This might be a camera driver, notifying when a new frame is available
def generate_data(callback, threadkill):
    while not threadkill.is_set():
        width = 1600
        data = np.zeros(width)
        data += np.cos(np.arange(0, 10*np.pi, 10*np.pi/width) - 
9*time.monotonic())
        data += np.cos(np.arange(0, 4*np.pi, 4*np.pi/width) + 
4*time.monotonic())
        callback(data)
        time.sleep(0.01)

class PyQtGraphTest(GraphicsLayoutWidget):

    # Signal to indicate new data acquisition
    # Note: signals need to be defined inside a QObject class/subclass
    data_acquired = pyqtSignal(np.ndarray)

    def __init__(self):
    
        super().__init__()

        self.setWindowTitle('Test pyqtgraph paint signals')
        self.resize(640, 400)
        self.plot = self.addPlot()
        self.spectrum = self.plot.plot()
        self.plot.enableAutoRange(pg.ViewBox.XYAxes)

        # Connect the signal
        self.data_acquired.connect(self.update_data)

        # Make and start the background thread to acquire data
        # Pass it the signal.emit as the callback function
        self.threadkill = Event()
        self.thread = Thread(target=generate_data, 
args=(self.data_acquired.emit, self.threadkill))
        self.thread.start()

    # Kill our data acquisition thread when shutting down
    def closeEvent(self, close_event):
        self.threadkill.set()

    # Slot to receive acquired data and update plot
    @pyqtSlot(np.ndarray)
    def update_data(self, data):
        self.spectrum.setData(data)

if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    window = PyQtGraphTest()
    window.show()
    if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
        sys.exit(app.exec_())



-- 
You received this message because you are subscribed to the Google Groups 
"pyqtgraph" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/pyqtgraph/33354545-4130-46cb-a9c6-91720c819780%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to