LoginSignup
4
7

More than 5 years have passed since last update.

tkinterのcanvasのevent時image書き換えで画像が表示されなかったからごり押しした

Posted at

要約:tkinterのcanvasのcreate_imageの画像データ(PhotoImage等)はglobal変数に持たせておけばとりあえずしのげる。


本題
tkinerのeventのコールバックでcanvasの画像(create_imageしたやつ)を更新(ex:マウスクリックされたピクセルを赤く塗る等)するとき、

#前略 import類
canvas = tkinter.Canvas("""オプションをだらだらと""")
PIL_Img = PIL.Image.open('foo.png')
#中略 (canvasに最初の画像を置いたりウインドウサイズを云々~~
def callback(event):
     PIL_Img.putpixel((event.x,event.y), (255, 0, 0, 255))
     event.widget.itemconfigure(1,image = PIL.ImageTk.PhotoImage(PIL_Img) )
#     ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑▲このへんが問題▲↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑

canvas.bind("<1>",callback)
#その他略

などとすると、画像が消える。どうやらコールバック内のみでしかPhotoImageの参照を持ってくれないらしい。create_ovalとかはちゃんと残るので逆に混乱する。なんでやねん。

個人的にかなり不本意だがグローバル変数に参照を持たせることでとりあえず解決した。

#前略 import類
global img """←こいつに画像の参照を持たせる"""
#中略 (root = tkinter.Tk()云々~~
canvas = tkinter.Canvas('~~~~略~~~~')
PIL_Img = PIL.Image.open('mask.png')
#中略 (canvasに最初の画像を置いたりウインドウサイズを云々~~
def callback(event):
     global img """←ここにもこう書かないと×"""
     PIL_Img.putpixel((event.x,event.y), (255, 0, 0, 255))
     img = PIL.ImageTk.PhotoImage(PIL_Img)
     event.widget.itemconfigure(tagOrId="foo",image = img)

canvas.bind("<1>",callback)
#後略 (root.mainloop()云々~~

解決のヒントになった記事
http://lrcgf.hatenablog.com/entry/2013/06/30/222918
tkinterの画像がどうのこうのについては
https://docs.python.jp/3/library/tkinter.html#bindings-and-events の25.1.6.9にもその記載があった
グローバル変数については https://qiita.com/msssgur/items/12992fc816e6adf32cff
を参考に
めっちゃハマった。つらみ。

4
7
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
7