Python matplotlib-直接在画布上绘制

Python matplotlib-直接在画布上绘制,python,matplotlib,Python,Matplotlib,由于动态更新的性能问题,我需要在画布上直接绘制很多矩形,作为非常低的级别,也就是说,不使用matplotlib.patches,就像我们使用经典GUI一样 更准确地说,我只想画一个矩形,而不是所有的图形 可能吗 下面是我使用Joe Kington提供的链接进行测试的代码 #!/usr/bin/env python3 from random import randint, choice import time import matplotlib.pyplot as plt import mat

由于动态更新的性能问题,我需要在画布上直接绘制很多矩形,作为非常低的级别,也就是说,不使用
matplotlib.patches
,就像我们使用经典GUI一样

更准确地说,我只想画一个矩形,而不是所有的图形

可能吗

下面是我使用Joe Kington提供的链接进行测试的代码

#!/usr/bin/env python3

from random import randint, choice
import time

import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
import matplotlib.colors as colors
import matplotlib

back_color = "black"
colors     = ['red', 'green', 'cyan', 'yellow']

width  = 16
height = 16

ax     = plt.subplot(111)
canvas = ax.figure.canvas

ax.set_xlim([0, width])
ax.set_ylim([0, height])

def update():
    global ax, canvas, colors, width, height

    x = randint(0, width - 1)
    y = randint(0, height - 1)

    rect = mpatches.Rectangle(
        (x, y), 1, 1,
        facecolor = choice(colors),
        edgecolor = back_color
    )

    start = time.time()
    ax.draw_artist(rect)
    canvas.blit(ax.bbox)
    print("draw >>>", time.time() - start)

timer = canvas.new_timer(interval = 1)
timer.add_callback(update)
timer.start()

plt.show()
在maco$下,我获得以下消息

Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/site-packages/matplotlib/backend_bases.py", line 1203, in _on_timer
    ret = func(*args, **kwargs)
  File "/Users/xxx/test.py", line 86, in update
    ax.draw_artist(rect)
  File "/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/site-packages/matplotlib/axes.py", line 2100, in draw_artist
    a.draw(self._cachedRenderer)
  File "/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/site-packages/matplotlib/artist.py", line 56, in draw_wrapper
    draw(artist, renderer, *args, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/site-packages/matplotlib/patches.py", line 393, in draw
    gc = renderer.new_gc()
  File "/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/site-packages/matplotlib/backends/backend_macosx.py", line 97, in new_gc
    self.gc.save()
RuntimeError: CGContextRef is NULL
对于特立独行的用户 我有一个好消息给那些想要玩以下代码和动画的Mac用户。我在Mac上重新安装了Maverick操作系统,没有任何软件,这称为干净安装,然后我安装了Anaconda和XQuark()

要使动画工作,只需在任何其他matplotlib导入之前使用以下两行即可

import matplotlib
matplotlib.use('TkAgg')

我认为这将适用于Anaconda支持的任何Mac操作系统。只有Maverick才需要使用XQuark。

您当前的代码有两个问题

  • 您试图在没有先绘制画布的情况下进行blit。您得到的错误是特定于后端的,但基本上是说画布的渲染器尚未初始化
  • 您没有将矩形艺术家添加到轴。因此,它不是通过调用ax.draw\u artist(rect)来绘制的
  • 下面是一个工作示例:

    from random import randint, choice
    import time
    import matplotlib.pyplot as plt
    import matplotlib.patches as mpatches
    
    back_color = "black"
    colors     = ['red', 'green', 'cyan', 'yellow']
    width, height = 16, 16
    
    fig, ax = plt.subplots()
    ax.set(xlim=[0, width], ylim=[0, height]) # Or use "ax.axis([x0,x1,y0,y1])"
    
    # Be sure to draw the canvas once before we start blitting. Otherwise
    # a) the renderer doesn't exist yet, and b) there's noting to blit onto
    fig.canvas.draw()
    
    def update():
        x = randint(0, width - 1)
        y = randint(0, height - 1)
    
        rect = mpatches.Rectangle(
            (x, y), 1, 1,
            facecolor = choice(colors),
            edgecolor = back_color
        )
        ax.add_artist(rect)
    
        start = time.time()
        ax.draw_artist(rect)
        fig.canvas.blit(ax.bbox)
        print("draw >>>", time.time() - start)
    
    timer = fig.canvas.new_timer(interval=1)
    timer.add_callback(update)
    timer.start()
    
    plt.show()
    
    不过,在这一点上,每次不增加一个新的艺术家会更有意义。相反,添加初始矩形并每次更新它。例如:

    from random import randint, choice
    import time
    import matplotlib.pyplot as plt
    import matplotlib.patches as mpatches
    
    back_color = "black"
    colors     = ['red', 'green', 'cyan', 'yellow']
    
    width, height = 16, 16
    
    fig, ax = plt.subplots()
    ax.set(xlim=[0, width], ylim=[0, height]) # Or use "ax.axis([x0,x1,y0,y1])"
    
    rect = mpatches.Rectangle(
        (0, 0), 1, 1,
        facecolor = choice(colors),
        edgecolor = back_color
    )
    ax.add_artist(rect)
    
    # Be sure to draw the canvas once before we start blitting. Otherwise
    # a) the renderer doesn't exist yet, and b) there's noting to blit onto
    fig.canvas.draw()
    
    def update():
        x = randint(0, width - 1)
        y = randint(0, height - 1)
        rect.set(xy=[x,y], facecolor=choice(colors))
    
        start = time.time()
        ax.draw_artist(rect)
        fig.canvas.blit(ax.bbox)
        print("draw >>>", time.time() - start)
    
    timer = fig.canvas.new_timer(interval=1)
    timer.add_callback(update)
    timer.start()
    
    plt.show()
    

    听起来你只是想用闪电游戏。我现在没有时间给出完整的答案,但请看一下这里的“为选定的绘图元素设置动画”部分:不,它也适用于补丁。你能举一个你正在尝试的例子吗?我已经把一个小的测试代码和错误信息放在一起了。我在Mac O$下。非常感谢你的建议,但这在我的Mac O$下仍然不起作用。你在Linux或Windows下测试过吗?我刚刚在Windows上测试成功。所以对于MacO$,有一个很大的错误。我将把它发布到
    matplotlib
    邮件列表中。是的,OSX后端可能很奇怪。如果可以,请改用
    TkAgg
    QtAgg
    GtkAgg
    等。(即在
    导入matplotlib.matplotlib.use('TkAgg')
    之前导入matplotlib.pyplot作为plt)如果您可以发布特定错误,可能有一个简单的解决方法。真是一团糟!在我理想的Python世界中不是很流行。。。我仍然在反对这一点。我已经找到了如何让你的代码在我的Mac上工作。我已经更新了我的问题。