使用PyQt和matplotlib快速重绘

2024-05-18 20:36:06 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试创建具有实时数据可视化的GUI应用程序。在

我想出的解决方案是使用众所周知的局部重绘技巧:

fig, axes = plt.subplots(nrows=2, ncols=1)

axes[0].set_{labels, limits}
axes[1].set_{labels, limits}    

fig.show()
fig.canvas.draw()
N = 2
graph_0 = axes[0].scatter([] * N, [] * N, s=[np.pi*5**2] * N, animated=True)
graph_1 = axes[1].scatter([] * N, [] * N, s=[np.pi*5**2] * N, animated=True)
bg_0 = fig.canvas.copy_from_bbox(axes[0].bbox)
bg_1 = fig.canvas.copy_from_bbox(axes[1].bbox)

while True:

    # Acquire new data
    tmp = [1, 2]  # *For example*

    # Clear plots
    fig.canvas.restore_region(bg_0)
    fig.canvas.restore_region(bg_1)

    # Set data to be visualized
    graph_0.set_offsets([(i+1, d) for i, d in enumerate(tmp)])
    graph_1.set_offsets([(i+1, d) for i, d in enumerate(tmp)])

    # Redraw
    axes[0].draw_artist(graph_0)
    axes[1].draw_artist(graph_1)
    fig.canvas.blit(axes[0].bbox)
    fig.canvas.blit(axes[1].bbox)

这个解决方案没问题,一切正常。在

之后,我尝试实现相同的方法,但使用PyQt后端(也添加一些控制元素)。在

代码如下:

^{pr2}$

您可能会在注释行下看到我使用的不同调用组合。在

所以,我希望每次点击button时,绘图都会被更新。它实际上是有效的,除了一个阻塞问题:

a)应用程序刚刚启动

enter image description here

b)按钮已单击一次

enter image description here

c)将焦点切换到另一个窗口并返回(此图是有偏移的图,但点放在旧坐标中)

enter image description here

有人能给我指路吗?在

提前谢谢!在

使用的版本:python3.4.3、matplotlib 1.4.3、PyQt 4.10.4。在


Tags: true应用程序labelsfig解决方案tmpgraphcanvas
2条回答

问题是,你在某个点抓取背景,然后再完全重新调整大小等到什么将在屏幕上结束。你需要做的是

  • 使用draw_idle让Qt决定何时真正触发完全重画
  • 在绘制之后,使用mpl事件堆栈获取背景

只有相关的方法:

    def prepare_figure(self):
        self.fig = Figure()
        self.axes = self.fig.add_subplot(111)

        self.axes.set_xlim((0, 6))
        self.axes.set_xlabel('seq.index')
        self.axes.set_ylim((0, 100))
        self.axes.set_ylabel('observation')

        N = 5
        self.graph = self.axes.scatter(
            [] * N, [] * N, s=[np.pi*5**2] * N,
            color='seagreen', animated=True)

        self.canvas = FigureCanvas(self.fig)
        # w = self.widget_mpl.width()
        # h = self.widget_mpl.height()
        # self.canvas.setFixedSize(w, h)

        self.layout_mpl.addWidget(self.canvas)

        # hook up to mpls event handling framework for draw events
        # this is emitted after the canvas has finished a full redraw
        self.canvas.mpl_connect('draw_event', self._draw_event)

        # ask the canvas to kindly draw it self some time in the future
        # when Qt thinks it is convenient
        self.canvas.draw_idle()

    def _draw_event(self, evt):
        # after drawing, grab the new background
        self.bg = self.canvas.copy_from_bbox(self.axes.bbox)

请看一下animation模块中的blitting代码,了解实现此功能所需的一整套函数(还有一个重新调整大小的事件),在强制重新绘制之后,您将需要重新blit最后一个数据。在

解决方案是不断检查和更新axes.bbox大小:

http://matplotlib.org/1.3.1/examples/old_animation/animation_blit_qt4.html

相关问题 更多 >

    热门问题