gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-11-28 21:33:13 25 4
gpt4 key购买 nike

这有点长,第一部分只是问题的描述,第二部分是我的“修复”是否正确的问题。

我是从 Python 编程开始的。我创建了一个与 Arduino 通信的程序,该程序读取我们熔化实验室炉子的温度。然后将温度用于 PID 算法,并将输出设置为 Arduino。通信是通过 pyserial 完成的。到目前为止,一切正常,包括实时绘制温度信号、PID 变量等。该脚本包括一个主循环和 3 个线程(串行通信、从串行端口读取的数据转换器、QWidget 的设定温度和 PID 算法的输出。这些值用于创建一个数组以在 pyqtgraph 中显示。最后,第三个线程将数据从数据移位器转移到 QWidget。

当使用我的 Linux-Notebook 时,一切正常,而且 GUI 从未停止更新。相反,当使用任何 Windows 主机时,我遇到一些 pyqtgraphs 停止刷新的问题。这种行为很奇怪,因为我或多或少在同一时间设置所有数据,使用相同的 numpy 数组(只是不同的列)——有些图刷新时间更长(几小时),有些更早停止(分钟)。在或多或少地搜索了互联网漏洞之后 ;-) 我认为我发现了问题:它是数据从线程到 GUI 的传递。一些虚拟代码来解释发生了什么:

DataUpdaterToGUI(QThread):

#sets the QWidget from main loop
def setGUI(self, gui):
self.gui = gui

def run()
while True:
with lock(): # RLock() Instance
copyArray = self.dataArray[:] # copy the array from the shifter
self.gui.plot1.copyArray(dataArray[:, 0], copyArray[:, 1])
self.gui.plot2.copyArray(dataArray[:, 0], copyArray[:, 2])
# self.gui.update()
# QApplication.instance().processEvents()

调用 self.gui.update() 和 processEvents() 都不会对结果产生任何影响:绘图会在一段时间后停止重绘(在 Windows 上)。

现在我有一个非常简单的例子,只是想确定我是否正确地使用了 threading-stuff。它工作正常,但我有一些问题:

  • 信号槽方法是否复制传递的数据?
  • 为什么不需要调用QWidget的update()方法?
  • 在使用信号时我必须使用任何类型的锁吗?

class Main(QWidget):
def __init__(self):
super().__init__()

self.layout = QGridLayout(self)
self.graph = pg.PlotWidget()
self.graph.setYRange(0,1000)
self.plot = self.graph.plot()
self.layout.addWidget(self.graph,0,0)
self.show()

def make_connection(self, data_object):
data_object.signal.connect(self.grab_data)

@pyqtSlot(object)
def grab_data(self, data):
print(data)
self.plot.setData(data)


class Worker(QThread):
signal = pyqtSignal(object)

def __init__(self):
super().__init__()

def run(self):
self.data = [0, 1]
i = 2
while True:
self.data[1] = i
self.signal.emit(self.data)
time.sleep(0.01)
i += 1

if __name__ == "__main__":
app = QApplication(sys.argv)

widget = Main()
worker = Worker()
widget.make_connection(worker)
worker.start()

sys.exit(app.exec_())

最佳答案

信号槽方法会复制传递的数据吗?信号是线程安全的,在传输数据时它们会进行复制,以便数据之前的线程和使用它的线程(GUI Thread)不会有冲突

为什么不用调用QWidget的update()方法? 其实pyqtgraph调用的是update方法,plot是一个PlotDataItem,所以查看源码setData()方法,它调用 updateItems()方法,在该方法中 curve 的 setData() 方法或 scatter属性被调用(根据图形类型),在曲线的情况下它是 setData()方法调用 updateData() 和 updateData()方法调用更新,在分散的情况下它是 setData()方法调用 addpoint() 和 addPoints()调用 invalidate(),这 invalidate()方法调用 update()。

在使用信号时我必须使用任何类型的锁吗?不需要,因为信号是线程安全的,所以 Qt 已经设置了保护措施来避免冲突。

关于python - 使用 pyqtgraph 和线程进行实时绘图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54961905/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com