[英]Real-Time-Plotting using pyqtgraph and threading
这有点长,第一部分只是问题的描述,第二部分是我的“修复”是否正确的问题。
我从python编程开始。 我创建了一个与Arduino通信的程序,该程序读取了我们熔炼实验室的熔炉温度。 然后将温度用于PID算法中,并将输出设置为Arduino。 通信是通过pyserial完成的。 到目前为止,所有工作都可以进行,包括实时绘制温度信号,PID变量等。 该脚本包括一个主循环和3个线程(串行通信,从串行端口读取的数据移位器,QWidget的设定温度和PID算法的输出。此值用于创建一个数组,以在pyqtgraph中显示。第三个线程将数据从datashifter移至QWidget。
使用我的Linux笔记本时,一切正常,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上)停止重绘。
现在,我有一个非常简单的示例,只想确保我是否正确使用了线程填充。 它工作正常,但我有一些问题:
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线程)不会发生冲突
为什么没有必要调用QWidget的update()方法? 实际上pyqtgraph调用了update方法,plot是一个PlotDataItem,因此,如果我们检查setData()方法的源代码,它将调用updateItems()方法,在该方法中, 曲线或散点属性的setData()方法称为(根据图形的类型),在曲线的情况下,其setData()方法调用updateData(),而updateData()方法调用update,在散布的情况下,其setData()方法调用addpoint(),以及addPoints()调用invalidate(),而此invalidate()方法调用update()。
使用信号时是否必须使用任何类型的锁? 不可以,因为信号是线程安全的,所以Qt已经设置了防护措施来避免冲突。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.