###要約: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
を参考に
めっちゃハマった。つらみ。