i have some trouble to make a gui responsive while plotting live data. So that the GUI doesn't freeze, I try to thread all of my activities. I want to realize the following:
- Recording data through a serial port
- Calculations for the later plot in a thread
- Plotting in a thread (currently via a QTimer, but when i drag the window, there is always a "small" freeze and the plot does not update on the drag)
1 and 2 is done, but now im not sure how to update my plot in a seperate thread.
My PlotWidget get initiated looks like this:
self.plottingDQ = [queue.deque(maxlen=100), queue.deque(maxlen=100), queue.deque(maxlen=100)]
self.graph = pg.PlotWidget()
self.barItem = pg.BarGraphItem(x0=self.plottingDQ[0], y0=self.plottingDQ[1], width=self.plottingDQ[2], height=1)
self.graph.addItem(self.barItem)
starting my threads is done via a button which is connected to this function. Writer-Thread is not relevant because it has no dependency on the plot. But the Calculator-Thread calculates the data for updating the plot
def startPlotting(self):
# not relevant for the example
self.csvData = queue.Queue()
self.csv = Writer(self.csvData)
self.csv.setDaemon(True)
self.csv.start()
self.calcData = queue.Queue()
self.calcPlot = Calculator(self.calcData, self.plottingDQ)
self.calcPlot.setDaemon(True)
self.calcPlot.start()
# Timer to update plot every x ms
self.timer = QTimer()
self.timer.timeout.connect(self.updatePlot)
self.timer.start(500)
Right now im updating my plot within the Qtimer every 500ms
def updatePlot(self):
print("update")
self.barItem.setOpts()
So every time i get some input from my serial port i just pass the data to my thread and call something like this:
def fromPort(self, data):
self.csvData.put(data)
self.calcData.put(data)
Inside my Calculator-Thread the data will be calculated and handed over to the plottingDQ which is connected to the BarGraphItem
class Calculator(threading.Thread):
def __init__(self, calcData, plottingDQ):
threading.Thread.__init__(self)
self.calcData = calcData
self.plottingDQ = plottingDQ
self.a = threading.Event()
self.a.set()
def run(self):
while self.a.isSet():
# Do some stuff here ...
# After the calculations, i write the data into the plottingDQ
self.plottingDQ[0].append(x)
self.plottingDQ[1].append(y)
self.plottingDQ[2].append(duration)
Is this the correct way to pass my calculated data from my Calcualtor-Thread into the deques which are used in the BarGraphItem? How can i update my BarGraphItem inside a thread?