2
from matplotlib import pyplot as p
from scipy import zeros
from Queue import Queue
import random
w,h = 320,200
black = zeros((h,w,3), dtype='uint8')
red = black.copy(); red[:,:,0] = 255
green = black.copy(); green[:,:,1] = 255
blue = black.copy(); blue[:,:,2] = 255
def ants():
from scipy import rand, dstack
return dstack([(255*rand(h,w)).astype('uint8')]*3)
fig = p.figure()
axs = [fig.add_subplot(1,3,i) for i in xrange(3)]
[ax.imshow(black) for ax in axs]
q = Queue()
def update_image(ax):
## this takes some time
import time
time.sleep(3)
ax.images[0].set_data(random.choice([red, green, blue]))
def hit(event):
if event.inaxes in axs:
update_axs = [event.inaxes]
else:
update_axs = axs
for ax in update_axs:
ax.images[0].set_data(ants())
p.draw()
# for ax in update_axs:
# update_image(ax)
# p.draw()
cid = fig.canvas.mpl_connect('button_press_event', hit)
p.show()
這裏是我的代碼,其中所有的按預期工作。然而,當我取消註釋事件處理程序中的這3行時,有一些問題我沒有想到。首先GUI凍結,而update_image
正在工作,其次第一個電話draw()
似乎沒有機會畫,因爲我沒有看到賽車螞蟻,而update_image
正在工作。在matplotlib中設置這種類型的東西的更好的方法是什麼?如何阻止matplotlib GUI線程凍結?
三江源,我已經嘗試類似的東西用'Queue'..so它很高興知道我是在正確的軌道上。你的版本上面的作品,但它也有一些奇怪的行爲。直到在圖形窗口中有一個GUI事件,工作者線程中的'draw()'似乎沒有任何效果,例如,一個鼠標移動事件。它使用'ipython -pylab'按預期進行更新,但這似乎會導致不穩定 - 大量的點擊可能會導致螞蟻持續存在,甚至數字窗口崩潰!是否有一些機制除了'p.draw()'這裏需要使圖形窗口重新適當地重繪? – wim
@wim:這是一個很好的問題。謝謝你指出。看起來,如果你聲明'matplotlib.use('TkAgg')',那麼當調用'ax.figure.canvas.draw()'或'p.draw()'時,軸被更新(沒有鼠標事件)。可能還有其他解決方案(如使用gtk,wx,qt或其他後端?),但我不知道完整的答案。 – unutbu
再次感謝您的回答。從GTKAgg切換到TkAgg後端解決了問題。出於好奇,你知道是否嚴格允許從worker線程中調用draw()嗎?它在我的本地機器上工作正常,但是當我嘗試通過'ssh -Y'會話使用它時,我得到'RuntimeError:主線程不在主循環中'由行ax.figure.canvas.draw )'。但是,如果我讓父線程在工作線程加入()後執行'draw()',那麼就沒有問題了。遠程機器和本地機器具有完全相同的python/matplotlib /後端設置。 – wim