読者です 読者をやめる 読者になる 読者になる

神野さんに言われました。

AIの勉強をしています @sesenosannko

tkinter.PhotoImageとガベージコレクション

Tkinter

こんにちは。

PythonでTkを扱うためのライブラリであるTkinterでの画像表示で詰まったところがあったのでメモしておきます。
Tkinterも初めて使うので、いろいろと分からないことが多いです。

三田祭に向けて音声分析アプリ的なものを作っていたのですが、分析結果をmatplotlibで描写して画像で表示しようとしたところで失敗しました。
そもそもTinterのcanvasに直接プロットする方法もあるらしいのですが、サイトを参考にしたところ望んでいる機能と共存させるのが難しそうなので、画像を保存して表示するという原始的な方法を試していきます。
コードは激しく省略しています。

def show_img():
    result_img = tkinter.PhotoImage(file = 'result.gif')
    canvas.create_image(300, 300, image = result_img)

これを用いて、

button1 = tkinter.Button(root, text="録音開始",
                    command=analysis) # result.gifを作る
button1.pack(padx=5, pady=5) 

button2 = tkinter.Button(root, text="結果を見る", 
                     command=show_img) # 表示されない!!
button2.pack(padx=5, pady=5)

canvas = tkinter.Canvas(root, width=600, height=600)    
canvas.place(x=200, y=150)

直感的にはこれで動くと思ったのですが、「結果を見る」ボタンを押しても何も起こりません。


[Tkinter-discuss] refreshing images

いろいろと調べた結果、このサイトによると新しいPhotoImageオブジェクトをレファレンスに登録しないと処理が終了した扱いとなり直ぐにガベージコレクションによって消去されることが原因であると分かりました。
僕はメモリ関係の知識が全く無いので、正直細かいことはよく分からないのですが、このようにPhotoImageオブジェクトをグローバル変数として登録することで避けられることが分かりました。
この辺りも勉強しないといけないですね。

def show_img():
    global result_img
    result_img = tkinter.PhotoImage(file = 'result.gif')
    canvas.create_image(300, 300, image = result_img)