豪情万千的杨桃 · 欢迎访问中国统计学会中国统计科学研究网· 4 周前 · |
不羁的勺子 · 实验室主任-智慧地铁福建省高校重点实验室· 1 月前 · |
个性的木耳 · “水货疫苗”致内地居民放弃赴港接种 ...· 1 月前 · |
风流的棒棒糖 · 《茶啊二中》讲的基本就是我了 - 知乎· 9 月前 · |
飞奔的蚂蚁 · 黄金十年,富二代网红简史_腾讯新闻· 1 年前 · |
我正在制作一个滚动图,它将绘制实时传感器数据,在x轴上显示时间。我对
tickStrings
的行为有点困惑。
我的代码基于下面的示例(来自 这里 )。当绘制的点数增加时,x轴字符串的数目会发生变化--有时会增加,有时会减少。它稳定一旦德克是完整的长度和‘滚动’开始。
是否有可能保持滴答字串之间的间距与绘图点的数目相同?我想,可能会使用一种方法,在添加新数据时替换空白的勾选字符串,但不知道如何做到这一点。
编辑:我希望实现的一个例子是 这里 。
import sys
import numpy as np
import datetime
from PyQt5.QtCore import QTime, QTimer
from pyqtgraph.Qt import QtGui
import pyqtgraph as pg
from collections import deque
import time
class TimeAxisItem(pg.AxisItem):
def __init__(self, *args, **kwargs):
super(TimeAxisItem, self).__init__(*args, **kwargs)
def tickStrings(self, values, scale, spacing):
return [int2dt(value).strftime("%H:%M:%S") for value in values]
def int2dt(ts):
return(datetime.datetime.fromtimestamp(ts))
class MyApplication(QtGui.QApplication):
def __init__(self, *args, **kwargs):
super(MyApplication, self).__init__(*args, **kwargs)
self.t = QTime()
self.t.start()
maxlen = 100
self.data_x = deque(maxlen=maxlen)
self.data_y = deque(maxlen=maxlen)
self.win = pg.GraphicsLayoutWidget()
self.win.resize(1000,600)
self.plot = self.win.addPlot(title='Scrolling real-time plot', axisItems={'bottom': TimeAxisItem(
orientation='bottom')})
self.curve = self.plot.plot()
self.tmr = QTimer()
self.tmr.timeout.connect(self.update)
self.tmr.start(1000)
self.y = 100
self.win.show()
def update(self):
x = int(time.time())
self.y = self.y + np.random.uniform(-1, 1)
self.data_x.append(x)
self.data_y.append(self.y)
time.sleep(2)
print(self.data_x)
print(self.data_y)
self.curve.setData(x=list(self.data_x), y=list(self.data_y))
def main():
app = MyApplication(sys.argv)
sys.exit(app.exec_())
if __name__ == '__main__':
main()
发布于 2022-02-06 08:45:26
由于问题被更新了更多的细节,这里有更具体的答案。我保留先前的答案,以帮助某人,以防有固定数量的蜱显示。
要准确地处理您想要的内容,首先需要将滴答频率设置为每秒1次。这可以通过设置
self.setTickSpacing(levels=[(1, 0)])
来完成。在您的示例中,您有一分钟的更新时间,在这种情况下,您需要使用
self.setTickSpacing(levels=[(60, 0)])
。
问题的第二部分是蜱的旋转-90度。旋转不是AxisItem实现的一部分。因此,我们必须重新实现drawPicture方法。完成滴答的旋转和平移。此外,为了有足够的高度,我们必须设置
self.fixedHeight = 150
以适应长的滴答线。
定间距是通过设置X轴的固定范围来实现的。为了达到滚动效果,我们必须在不附加任何数据的情况下隐藏第一滴滴。这是用
ticks = [(1.0, ticks[0][1][self.hide_ticks:])]
行完成的。
值得注意的是,我的解决方案适合你的具体情况。否则,必须使用fixedHeight和drawPicture方法的旋转部分。另外,队列的
maxlen
必须降低到10,这样就不会重叠。
这是完整的代码:
import datetime
import sys
import time
from collections import deque
import numpy as np
import pyqtgraph as pg
from PyQt5.QtCore import QTime, QTimer
from pyqtgraph import debug as debug
from pyqtgraph.Qt import QtGui
class TimeAxisItem(pg.AxisItem):
hide_ticks = 0
def __init__(self, *args, **kwargs):
super(TimeAxisItem, self).__init__(*args, **kwargs)
# Paint tick every 1 second
self.setTickSpacing(levels=[(1, 0)])
# Paint tick every 1 minute
# self.setTickSpacing(levels=[(60, 0)])
# Set fixed tick height
self.fixedHeight = 150
def tickStrings(self, values, scale, spacing):
return [int2dt(value).strftime("%Y-%m-%d %H:%M:%S") for value in values]
def drawPicture(self, p, axisSpec, tickSpecs, textSpecs):
profiler = debug.Profiler()
p.setRenderHint(p.RenderHint.Antialiasing, False)
p.setRenderHint(p.RenderHint.TextAntialiasing, True)
## draw long line along axis
pen, p1, p2 = axisSpec
p.setPen(pen)
p.drawLine(p1, p2)
# p.translate(0.5,0) ## resolves some damn pixel ambiguity
## draw ticks
for pen, p1, p2 in tickSpecs:
p.setPen(pen)
p.drawLine(p1, p2)
profiler('draw ticks')
# Draw all text
if self.style['tickFont'] is not None:
p.setFont(self.style['tickFont'])
p.setPen(self.textPen())
bounding = self.boundingRect().toAlignedRect()
p.setClipRect(bounding)
for rect, flags, text in textSpecs:
p.save() # save the painter state
p.translate(rect.center()) # move coordinate system to center of text rect
p.rotate(-90) # rotate text
p.translate(-rect.center()) # revert coordinate system
p.translate(-65, 0) # Move rotated tick down by 65 pixels
p.drawText(rect, int(flags), text)
p.restore() # restore the painter state
profiler('draw text')
def tickValues(self, minVal, maxVal, size):
if minVal == 0:
return []
else:
ticks = super().tickValues(minVal, maxVal, size)
ticks = [(1.0, ticks[0][1][self.hide_ticks:])]
return ticks
def int2dt(ts):
return (datetime.datetime.fromtimestamp(ts))
class MyApplication(QtGui.QApplication):
def __init__(self, *args, **kwargs):
super(MyApplication, self).__init__(*args, **kwargs)
self.t = QTime()
self.t.start()
maxlen = 10
self.data_x = deque(maxlen=maxlen)
self.data_y = deque(maxlen=maxlen)
self.win = pg.GraphicsLayoutWidget()
self.win.resize(1000, 600)
self.axis_x = TimeAxisItem(orientation='bottom')
self.plot = self.win.addPlot(title='Scrolling real-time plot', axisItems={'bottom': self.axis_x})
self.curve = self.plot.plot()
self.tmr = QTimer()
self.tmr.timeout.connect(self.update)
self.tmr.start(1000)
self.y = 100
self.win.show()
def update(self):
x = int(time.time())
self.y = self.y + np.random.uniform(-1, 1)
self.data_x.append(x)
self.data_y.append(self.y)
time.sleep(1)
# Set fixed range
self.plot.setXRange(self.data_x[0] - self.data_x.maxlen + len(self.data_x),
self.data_x[0] + len(self.data_x) - 1, padding=0)
# Hide ticks without data attached to it, to achieve scrolling effect
self.axis_x.hide_ticks = self.data_x.maxlen - len(self.data_x)
self.curve.setData(x=list(self.data_x), y=list(self.data_y))
def main():
app = MyApplication(sys.argv)
sys.exit(app.exec_())
if __name__ == '__main__':
main()
发布于 2022-02-02 12:00:41
要设置固定数量的刻度,还必须重写
tickValues
方法。此方法生成滴答值,
tickStrings
方法给出这些值的字符串表示--在您的情况下转换为人类可读的时间。
下面是您可以在代码中使用的TimeAxisItem示例:
class TimeAxisItem(pg.AxisItem):
nticks = 6
def __init__(self, *args, **kwargs):
super(TimeAxisItem, self).__init__(*args, **kwargs)
def tickStrings(self, values, scale, spacing):
return [int2dt(value).strftime("%H:%M:%S") for value in values]
豪情万千的杨桃 · 欢迎访问中国统计学会中国统计科学研究网 4 周前 |
不羁的勺子 · 实验室主任-智慧地铁福建省高校重点实验室 1 月前 |
风流的棒棒糖 · 《茶啊二中》讲的基本就是我了 - 知乎 9 月前 |
飞奔的蚂蚁 · 黄金十年,富二代网红简史_腾讯新闻 1 年前 |