pyqtgraph 滚动图:分块绘图,在当前窗口中仅显示最新的 10 秒样本
Posted
技术标签:
【中文标题】pyqtgraph 滚动图:分块绘图,在当前窗口中仅显示最新的 10 秒样本【英文标题】:pyqtgraph scrolling plots: plot in chunks, show only latest 10s samples in current window 【发布时间】:2021-03-27 15:59:25 【问题描述】:我在使用 pygtgraph 滚动图时遇到问题
预期结果
预期结果与pyqtgraph-examples-scrolling plots-plot5非常相似
X 值是时间,可以通过一个简单的函数生成。 Y 值是随机值。
每 10 秒采样为一个块,每个图可以有最大值。 30 秒样本,这意味着 3 个块。 当前绘图窗口仅显示最近 10 秒的样本
例如,现在总共有 60 秒的样本:
50s-60s之间的数据会在当前窗口查看 30s-50s之间的数据可以通过鼠标向后拖动x轴来查看 0-30s之间的数据不会显示我的代码
我当前的代码如下,它只能显示最新的30s数据。
import pyqtgraph as pg
from pyqtgraph.Qt import QtCore, QtGui
import numpy as np
import random
win = pg.GraphicsLayoutWidget(show=True)
win.setWindowTitle('Scrolling Plots')
p1 = win.addPlot()
p1.setYRange(0,10)
xVal = [0]
yVal = [0]
def genTime(): # used to generate time
t = 0
while True:
t += np.random.random_sample()
yield t
t = np.ceil(t)
xTime = genTime()
#=====================================================
viewSize = 10 # current window show only latest 10s data
plotSize = 30 # plot 30s data -> 3 chunk
lstCurves = [] # List for Curves
def update():
global p1, xVal, yVal, lstCurves
#for c in lstCurves:
# c.setPos(xVal[-1], 0)
i = np.ceil(xVal[-1]) % viewSize # e.g. when time is 9.2s -> one 10s view size is full, append to curves list as one chunk
if i == 0:
curve = p1.plot()
lstCurves.append(curve)
xValLast = xVal[-1]
yValLast = yVal[-1]
xVal = [xValLast]
yVal = [yValLast]
while len(lstCurves) > 3: # max 3 chunk (30 s)
p1.removeItem(lstCurves.pop(0)) # remove the oldest 10s
else:
curve = lstCurves[-1] # latest 10s curve
xVal.append(next(xTime))
yVal.append(random.randint(0,9))
curve.setData(xVal, yVal)
print(len(lstCurves))
#======================================================
timer = pg.QtCore.QTimer()
timer.timeout.connect(update)
timer.start(1000)
## Start Qt event loop unless running in interactive mode or using pyside.
if __name__ == '__main__':
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
问题
我尝试过使用curve.setPos(xx, 0)
,看起来整条曲线都在沿x轴移动,但是X值和Y值的映射关系被破坏了
我还尝试使用setXRange()
动态更改update()
func 中的x 轴显示范围。但是在这种情况下,我不能再用鼠标拖回x轴来查看旧数据了。
我的英文不好,希望你能理解我的问题。任何建议将不胜感激!
【问题讨论】:
真的需要用鼠标拖动来选择视图吗?或者它可以是,例如,一个滑块?。 【参考方案1】:问题
您的代码不符合您的要求的原因是:
当您拖动查看其他块时,您禁用了绘图的自动自动范围,之后,您每次想要查看新数据时都必须手动拖动绘图。此外,默认情况下,绘图的自动范围将覆盖您正在绘制的所有数据。 当您在update
函数中使用setRange()
方法时,它会在您每次向数据中添加另一个值时强制该范围。然后拖动将无法按您的意愿工作
你能做什么
好吧,从我的角度来看,使用鼠标拖动来可视化其他数据不是很方便,我建议使用外部小部件来控制要查看的数据的范围,例如,滑块、滚动条、旋转盒子, ...
QScrollBar
可以完成这项工作,并且在 GUI 中看起来很美观。
在我的替代解决方案之前,我有一个建议给你:
使用对象来创建您的小部件,生成一个类并将变量用作属性,这样您就可以避免使用关键字global
,并且您可以将小部件重复用于其他目的。
替代解决方案
试试这个:
import sys
import random
import numpy as np
import pyqtgraph as pg
from pyqtgraph.Qt import QtCore, QtGui
class MyApp(QtGui.QWidget):
def __init__(self):
QtGui.QWidget.__init__(self)
## Creating the Widgets and Layouts
self.plot_widget = pg.PlotWidget()
self.layout = QtGui.QVBoxLayout()
self.sbutton = QtGui.QPushButton("Start / Continue")
self.ebutton = QtGui.QPushButton("Stop")
self.timer = pg.QtCore.QTimer()
self.scroll = QtGui.QScrollBar(QtCore.Qt.Horizontal)
## Creating the variables and constants
self.data = [[0], [random.randint(0,9)]] ## [xVal, yVal] to create less variables
self.plot_item = self.plot_widget.plot(*self.data)
self.plot_widget.setYRange(0, 10)
self.xTime = self.genTime()
self.vsize = 10
self.psize = 30
## Building the Widget
self.setLayout(self.layout)
self.layout.addWidget(self.sbutton)
self.layout.addWidget(self.ebutton)
self.layout.addWidget(self.plot_widget)
self.layout.addWidget(self.scroll)
## Changing some properties of the widgets
self.plot_widget.setMouseEnabled(x=False, y=False)
self.ebutton.setEnabled(False)
self.scroll.setEnabled(False)
self.scroll.setMaximum(self.psize-self.vsize)
self.scroll.setValue(self.psize-self.vsize)
## Coneccting the signals
self.sbutton.clicked.connect(self.start)
self.ebutton.clicked.connect(self.stop)
self.timer.timeout.connect(self.update)
self.scroll.valueChanged.connect(self.upd_scroll)
def genTime(self): # used to generate time
t = 0
while True:
t += np.random.random_sample()
yield t
t = np.ceil(t)
def upd_scroll(self):
val = self.scroll.value()
xmax = np.ceil(self.data[0][-1+self.vsize-self.psize+val])-1
xmin = xmax-self.vsize
self.plot_widget.setXRange(xmin, xmax)
def update(self):
num = len(self.data[0])
if num <= self.psize:
self.plot_item.setData(*self.data)
else:
self.plot_item.setData(
self.data[0][-self.psize:],
self.data[1][-self.psize:]
)
if num == self.vsize:
self.scroll.setEnabled(True)
self.data[0].append(next(self.xTime))
self.data[1].append(random.randint(0,9))
if num > self.vsize :
self.upd_scroll()
def start(self):
self.sbutton.setEnabled(False)
self.ebutton.setEnabled(True)
self.timer.start(100)
def stop(self):
self.sbutton.setEnabled(True)
self.ebutton.setEnabled(False)
self.timer.stop()
self.upd_scroll()
def closeEvent(self, event):
self.timer.stop()
event.accept()
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
window = MyApp()
window.show()
sys.exit(app.exec_())
它可能看起来像这样:
【讨论】:
很高兴再次见到你,很有帮助。以上是关于pyqtgraph 滚动图:分块绘图,在当前窗口中仅显示最新的 10 秒样本的主要内容,如果未能解决你的问题,请参考以下文章