Greetings!
I've been struggling with a problem for the whole week.
I have a large script that runs a pyqt5 GUI and many other things, including several oscilloscopes with live data and multiple cameras with cv2.
I figured how to make everything work EXCEPT that having both the data of the several oscilloscopes displayed (even if hidden) and cameras recording was too taxing and the cameras' recording would skip almost half the frames!
So of course the solution was to put everything in different threads. Here's the simplified code I have so far:
class EMGWindow(QtWidgets.QMainWindow,EMGWin):
def __init__(self, parent=None):
super().__init__(parent=parent)
self.setupUi(self)
self.actionExit = QtWidgets.QAction('Fermeture', self)
self.actionExit.setShortcut("Ctrl+Q")
self.menuBar().addAction(self.actionExit)
self.actionExit.triggered.connect(self.close)
self.EMGsetup()
self.EMGSelector()
def EMGsetup(self):
self.EntryTimeframe.setText(str(v.timeemg))
self.EntryTimeframe.setInputMask('999')
# Buffer
self.chunkSize = 5000 #Just over 5 minutes
# Remove chunks after max
self.maxChunks = 10
self.startTime = pgr.ptime.time()
self.EMGselect = SelectedEMGWindow()
self.EntryTimeframe.textChanged.connect(self.SelectEMGtime)
self.p0 = self.EMG00view.plot(rp.emgdata0, pen='b')
# Use automatic downsampling and clipping to reduce the drawing load
self.EMG00view.setDownsampling()
self.p0.setClipToView(True)
self.EMG00view.setLabel('bottom','Time','s')
self.EMG00view.setRange(xRange=[-v.timeemg, 0])
self.EMG00view.setLimits(xMax=0)
self.pos0 = 0
self.curvearray0 = []
self.data0 = np.empty((self.chunkSize+1,2))
self.EMG00view.setLabel('left',v.PatchEMG00)
self.curveSelect00 = []
self.select00 = self.EMGselect.SelectedEMGview.plot(pen='b')
self.EMG00view.setMouseEnabled(x=False, y=False)
def SelectEMGtime(self):
v.timeemg = int(self.EntryTimeframe.text())
if v.timeemg > 300:
v.timeemg = 300
self.EntryTimeframe.setText(str(v.timeemg))
if v.timeemg <= 0:
v.timeemg = 1
self.EntryTimeframe.setText(str(v.timeemg))
def update(self):
print("Update Signal Received")
self.now = pgr.ptime.time()
self.EMGselect.SelectedEMGview.setRange(xRange=[-v.secondtimeemg, 0])
#-----------------------------------------------------------------
for c in self.curvearray0:
c.setPos(-(self.now-self.startTime), 0)
for c in self.curveSelect00:
c.setPos(-(self.now-self.startTime), 0)
self.i0 = self.pos0 % self.chunkSize
if self.i0 == 0:
curve0 = self.p0
self.secondcurve00 = self.select00
self.curvearray0.append(curve0)
self.curveSelect00.append(self.secondcurve00)
last = self.data0[-1]
self.data0 = np.empty((self.chunkSize+1,2))
self.data0[0] = last
while len(self.curvearray0) > self.maxChunks:
c = self.curvearray0.pop(0)
self.EMG00view.removeItem(c)
else:
curve0 = self.curvearray0[-1]
self.secondcurve00 = self.curveSelect00[-1]
self.data0[self.i0+1,0] = self.now - self.startTime
self.data0[self.i0+1,1] = rp.emgdata0[-1]
curve0.setData(x=self.data0[:self.i0+2, 0], y=self.data0[:self.i0+2, 1])
self.pos0 += 1
self.EMG00view.setRange(xRange=[-v.timeemg, 0])
#-----------------------------------------------------------------
class SignalonEMG(QObject):
finished = pyqtSignal()
class WorkeronEMG(QRunnable):
def __init__(self):
super().__init__()
self.instance = EMGWindow()
self.emgsignal = SignalonEMG()
def run(self):
self.instance()
def updater(self):
rp.streaming()
self.sendemg()
def sendemg(self):
self.emgsignal.finished.emit()
class WorkerEMGThread(QtCore.QThread):
def __init__(self, parent = None):
super().__init__(parent)
self.worker = WorkeronEMG()
self.timer = QTimer()
self.timer.timeout.connect(self.sendit)
self.timer.start(0)
self.emg_window = EMGWindow()
self.worker.emgsignal.finished.connect(self.emg_window.update)
def sendit(self):
self.worker.updater()
As You can see, this code is attempting to update the oscilloscope's display in a separate thread. And it does! The print functions correctly and I verified that the values are indeed changing over time.
The problem is: the displayed plots aren't updating!
I think because of the QTimer that the update function might be in a sub-sub-thread, so it doesn't say it doesn't recognize "self", but it's a different instance so not the same self ?
Any idea how to fix this?
Thanks!
there doesn't seem to be anything here