1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

tkinterで画像が表示されない現象について(ガベージコレクション)

Last updated at Posted at 2024-09-28

はじめに

tkinterでデスクトップアプリ上に画像を表示しようとしたが、画像が表示されない不具合が発生した。
本記事ではその解決方法をまとめる。

環境

tkinter: 8.6

現象の再現

import tkinter
from PIL import Image, ImageTk

root = tkinter.Tk()
root.geometry('400x300')

img = Image.open('dog1.jpg')

def create_label():
    imgtk = ImageTk.PhotoImage(img) 
    label = tkinter.Label(root, width=300, height=300, image=imgtk)
    label.grid()

create_label()
root.mainloop()

実行結果

上記コードを実行するとこのように画像が表示されない。
pic1.png

原因

上記のコードでは、表示させたい画像を定義しているimgtkcreate_label()関数の中でのみ存在しており、変数のスコープも関数内に限られています。
そのため、create_label()関数の外からimgtkへの参照(アプリケーション側からの参照)ができなくなります。
その結果、参照されなくなったこの変数がメモリから解放され、ガベージコレクションが発生してしまったのです。

対処法

Labelウィジェットのプロパティに明示的に画像を設定し、ガベージコレクションの対象から除外する。
具体的には以下のコードを追加してあげます。

# labelはtkinter.Labelのインスタンスであり、そのimageプロパティに画像を指定。
# これで参照を保持
label.image = imgtk

修正後のコード

import tkinter
from PIL import Image, ImageTk

root = tkinter.Tk()
root.geometry('400x300')

img = Image.open('dog1.jpg')

def create_label():
    imgtk = ImageTk.PhotoImage(img) 
    label = tkinter.Label(root, width=300, height=300, image=imgtk)
    label.image = imgtk  # ←これを追加
    label.grid()

create_label()
root.mainloop()

修正後の実行結果

pic2.png

まとめ

ローカルスコープ内で定義した画像(変数も含む)は外部(アプリケーション全体)からアクセスできなくなり、結果として白一色の画像しか表示されなくなる。
回避方法として、ウィジェットのプロパティに明示的に変数を保持させる。
あるいは局所変数として作成しないことで正常に画像が表示し続けることができる。

1
2
0

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
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?