More generally, you should not directly interact with any part of the GUI from outside the main thread. I remember being surprised by this when I first started working with Qt, but found that it was true of every other GUI toolkit as well.
On Thu, Nov 16, 2017 at 6:46 PM, Patrick <[email protected]> wrote: > 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 > <https://groups.google.com/d/msgid/pyqtgraph/33354545-4130-46cb-a9c6-91720c819780%40googlegroups.com?utm_medium=email&utm_source=footer> > . > > For more options, visit https://groups.google.com/d/optout. > -- 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/CACZXET_ionT6kVNPc_s-A4QKDm2p24%3DYdRUxKHVPA2J%3D9CRvqQ%40mail.gmail.com. For more options, visit https://groups.google.com/d/optout.
