正在线程内更新pyqtgraph BarGraphItem



在绘制实时数据时,我很难让gui做出响应。为了使GUI不会冻结,我尝试线程化我的所有活动。我想实现以下内容:

  1. 通过串行端口记录数据
  2. 线程中后期绘图的计算
  3. 在线程中绘图(当前通过QTimer,但当我拖动窗口时,总是会出现"小"冻结,绘图不会在拖动时更新(

1和2已经完成,但现在我不确定如何在单独的线程中更新我的绘图。

我的PlotWidget启动如下:

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)

启动我的线程是通过一个连接到此函数的按钮完成的。Writer线程不相关,因为它不依赖于绘图。但是计算器线程计算用于更新绘图的数据

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)

现在我每500ms 更新一次Qtimer内的绘图

def updatePlot(self):
print("update")
self.barItem.setOpts()

因此,每次我从串行端口获得一些输入时,我都会将数据传递给线程,并调用类似的东西:

def fromPort(self, data):
self.csvData.put(data)
self.calcData.put(data)

在我的计算器线程中,数据将被计算并移交给连接到BarGraphItem 的plottingDQ

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)

这是将我的计算数据从Calcualtor线程传递到BarGraphItem中使用的deques的正确方法吗?如何在线程内更新BarGraphItem?

您对此进行编程的方式看起来不错。";口吃;似乎是一个";更新块";在拖动过程中。

尝试通过将pg.QtGui.QApplication.processEvents((添加到updatePlot函数来强制更新,如下所述:

def updatePlot(self):
print("update")
self.barItem.setOpts()
pg.QtGui.QApplication.processEvents()

最好使用Qthread来处理这个问题,让一个工作线程在应用程序循环中进行绘图更新。

最新更新