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行のコメントを外すと、私が期待していないいくつかの問題があります。最初にupdate_image
が動作している間にGUIがフリーズし、第2にdraw()
への最初の呼び出しでは、update_image
が動作している間に、レースのアリを見ないのでペイントする機会を得られないようです。 matplotlibにこの種のものを設定するより良い方法は何ですか?それで、スムーズに動作しますか?matplotlib GUIスレッドがフリーズするのを止めるには?
ありがとうを、私はそれは私が正しい軌道上にあった知ってうれしいですQueue'..so 'ですでに似た何かをしようとしていました。上記のあなたのバージョンは動作しますが、それはまたいくつかの奇妙な動作をします。 FigureウィンドウにGUIイベントがあるまで、ワーカースレッドの 'draw()'は何の効果もないようです。マウス移動イベント。それは 'ipython -pylab'で期待どおりに更新されますが、これは不安定になります - たくさんのクリックがアリを継続させ、Figureウィンドウもクラッシュする可能性があります! Figureウィンドウを適切に再描画させるためにここに必要な 'p.draw()'以外のメカニズムがありますか? – wim
@wim:それはすばらしい質問です。それを指摘していただきありがとうございます。 'matplotlib.use( 'TkAgg')'を宣言すると、 'ax.figure.canvas.draw()'や 'p.draw()'が呼び出されたときに軸が更新されます(マウスイベントなし)。おそらく他のソリューション(gtk、wx、qt、または他のバックエンドを使用しているようなもの)がありますが、完全な答えはわかりません。 – unutbu
答えにもう一度感謝します。 GTKAggからTkAggバックエンドに切り替えることで問題は解決しました。奇妙なことから、ワーカースレッド内からdraw()を厳密に呼び出すことが許可されているかどうかは分かりますか?私のローカルマシンでは問題なく動作しますが、 'ssh -Y'セッションで使用しようとすると、' RuntimeError:メインスレッドがメインループにはない 'という行の' ax.figure.canvas.draw( ) '。しかし、親スレッドが 'draw()'をワーカースレッド 'join()'の後に実行させる場合、問題はありません。リモートマシンとローカルマシンはまったく同じpython/matplotlib/backend設定を持っています。 – wim