在线程内更新 pyqtgraph BarGraphItem

Posted

技术标签:

【中文标题】在线程内更新 pyqtgraph BarGraphItem【英文标题】:Updating pyqtgraph BarGraphItem inside a thread 【发布时间】:2021-03-18 20:53:49 【问题描述】:

在绘制实时数据时让 gui 响应时遇到了一些麻烦。为了使 GUI 不会冻结,我尝试线程化我的所有活动。我想实现以下几点:

    通过串口记录数据 线程中后期绘图的计算 在线程中绘图(当前通过 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-Thread 不相关,因为它不依赖于情节。但是计算器线程计算数据以更新绘图

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)

现在我每 500 毫秒在 Qtimer 中更新我的绘图

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

所以每次我从串口获得一些输入时,我都会将数据传递给我的线程并调用如下内容:

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

在我的 Calculator-Thread 中,数据将被计算并交给连接到 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)

这是将我的计算数据从我的计算器线程传递到 BarGraphItem 中使用的双端队列的正确方法吗?如何在线程中更新我的 BarGraphItem?

【问题讨论】:

【参考方案1】:

您的编程方式看起来不错。 “卡顿”的根本原因似乎是在拖动过程中出现了“更新块”。

尝试通过将 pg.QtGui.QApplication.processEvents() 添加到您的 updatePlot 函数来强制更新,如 described here:

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

【讨论】:

【参考方案2】:

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

【讨论】:

以上是关于在线程内更新 pyqtgraph BarGraphItem的主要内容,如果未能解决你的问题,请参考以下文章

PyQt5使用pyqtgraph绘图时UI卡顿的解决

PySide / PyQtGraph 访问主 Qt 事件线程

使用 pyqtgraph 和线程进行实时绘图

PyQt4 中的 QThreading PyQtGraph PlotWidgets

pyqtgraph ImageView 在多线程时冻结

pyqtgraph 主窗体内的绘图(qt 设计器)