我正在开发一个基于Qt的应用程序(实际上是在PyQt中,但我认为这不相关),其中一部分涉及实时绘制可能连续的数据流到图表上。
我通过创建一个派生自QWidget
的类来实现这一点,该类缓冲传入的数据,并且每隔30ms(默认情况下)绘制图形。在__init__()
中,创建了QPixmap
,并且在QTimer
的每个刻度上,(1)图表向左移动了新数据占用的像素数,(2)在空间中绘制的矩形,(3)绘制的点,以及(4)update()
在小部件上调用,如下(减少):
# Amount of pixels to scroll
scroll=penw*len(points)
# The first point is not plotted now, so don't shift the graph for it
if (self.firstPoint()):
scroll-=1
p=QtGui.QPainter(pm)
# Brush setup would be here...
pm.scroll(0-scroll, 0, scroll, 0, pm.width()-scroll, pm.height())
p.drawRect(pm.width()-scroll, 0, scroll, pm.height())
# pen setup etc happens here...
offset=scroll
for point in points:
yValNew = self.graphHeight - (self.scalePoint(point))
# Skip first point
if (not(self.firstPoint())):
p.drawLine(pm.width()-offset-penw, self.yVal, pm.width()-offset, yValNew)
self.yVal = yValNew
offset-=penw
self.update()
最后,paintEvent
只是将像素图绘制到小部件上:
p = QtGui.QPainter(self)
p.drawPixmap(0, 0, self.graphPixmap)
据我所知,这应该可以正常工作,但是,当数据被非常快速地接收时(即每个刻度上绘制整个图形),并且小部件大于特定大小(大约700px), 700px区域左侧的所有内容都相当滞后。这可能最好在此视频中得到证明:http://dl.dropbox.com/u/1362366/keep/Graph_bug.swf.html(由于帧速率较低,视频有点滞后,但效果明显)
任何想法可能导致这个或我可以尝试的事情?
感谢。
答案 0 :(得分:0)
我不是百分百确定这是否是问题,但我想我至少可以做出一些贡献。
self.update()
是一个异步调用,它会在稍后再次到达主事件循环时在某个时刻导致绘制事件。所以它让我想知道你的绘图是否有问题,因为你修改pixmap与实际在paintEvent中实际使用时之间存在同步问题。几乎看起来你需要这个确切的代码才能在你的paintEvent中锁定,但这听起来很顽皮。
要进行快速测试,您可以尝试在调用更新后立即强制事件循环刷新:
self.update()
QtGui.QApplication.processEvents()
不确定会解决它,但值得一试。
这实际上可能是使用repaint()
并导致直接绘制事件的正确情况,因为您使用受控帧率执行“动画”:self.repaint()
我发现了一个类似的问题,有人试图实时绘制心脏监护仪的图形:http://qt-project.org/forums/viewthread/10677
也许您可以尝试重构类似的代码。他不是将绘画分成两个阶段,而是使用QLabel作为显示窗口小部件,将像素图设置为QLabel,并立即绘制整个图形,而不是依赖于对widget的调用。(update()