質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Tkinter

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

3079閲覧

tkinter で同時に複数のウィンドウを生成し画像を表示したい

CleanDiesel

総合スコア15

Tkinter

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2020/04/01 13:41

編集2020/04/01 13:47

Tkinterで画像を載せたウィンドウを複数生成したいのですが、画像が表示されないです。

python

1from tkinter import * 2from PIL import ImageTk, Image 3 4def generate_mother(): 5 for i in range(10): 6 generate() 7 8def generate(): 9 root2 = Toplevel() 10 image1 = ImageTk.PhotoImage(Image.open("./test.gif")) 11 label2 = Label(root2, image = image1, bg = "black") 12 label2.pack() 13 # root2.mainloop() 14 15root = Tk() 16button = Button(root, text = "foo", bg = "red", command = generate_mother) 17button.pack() 18 19root.mainloop()

エラーは生成されませんでした。ただ画像が表示されないです。
###試したこと
上記コードのコメント部のように追記すると画像が表示されますがgenerate()が一回しか実行されません。

そこでコメント部を追記しThreadingを使って同時実行したところエラーが発生しました。
それがこれ

python

1from tkinter import * 2from PIL import ImageTk, Image 3import threading 4 5def generate_mother(): 6 for i in range(10): 7 threading.Thread(target=generate).start() 8 9def generate(): 10 root2 = Toplevel() 11 image1 = ImageTk.PhotoImage(Image.open("./test.gif")) 12 label2 = Label(root2, image = image1, bg = "black") 13 label2.pack() 14 root2.mainloop() 15 16root = Tk() 17button = Button(root, text = "foo", bg = "red", command = generate_mother) 18button.pack() 19 20root.mainloop()

エラー

Exception in thread Thread-8: Traceback (most recent call last): File "/usr/lib/python3.6/threading.py", line 916, in _bootstrap_inner self.run() File "/usr/lib/python3.6/threading.py", line 864, in run self._target(*self._args, **self._kwargs) File "test.py", line 37, in generate root2.mainloop() File "/usr/lib/python3.6/tkinter/__init__.py", line 1283, in mainloop self.tk.mainloop(n) RuntimeError: Calling Tcl from different appartment

このエラーがThread-8の番号の部分が変わっていっぱい出てきます。
この場合画像が表示されないウィンドウと表示されるウィンドウとあります。
###環境
python3.6.9
tkinter8.6

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

問題の原因

generate関数が終了した後に、
Pythonのガベージコレクタにより画像のリソースが破棄される為。

解決策: 何処かに参照を保存する

python

1# グローバルで TkImage() を保持するためのリストを作り 2image_holder = [] 3 4# generage()関数内で 5image_holder.append(image1)

もっと良い管理方法もあると思いますが、(プログラムの構成次第)
取り合えずこれで表示は出来ると思います。

tkinterでは各ウィジェットは引数に親要素の指定(キーワード引数でmaster=)があるので、
その辺りを調べてみてください。

追記: 関連質問を参考に、label2.image = image でも画像表示できました。
何処かに変数の参照を残せればよいので、.image の部分は何でもよいです。

image1 = ImageTk.PhotoImage(Image.open("./test.gif")) label2 = Label(root2, image = image1, bg = "black") label2.image = imabe1

Toplevel() を入れた root2 変数も関数が終わった後も、
ウィンドウが残り続けているのを不思議に思われるかもしれませんが、
これはライブラリ特有の事情があり、

tkinterが行っているのは、tcl という別プログラミング言語の環境にコマンド文字列を送っているだけで
ウィジェットの管理などは tcl 側で行われている為影響しません。
root2変数が Python 内では破棄された後も、開かれたウィンドウは tcl 側で残り続けます。


追記: 関連

投稿2020/04/01 14:48

編集2020/04/02 06:31
teamikl

総合スコア8760

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

CleanDiesel

2020/04/03 16:24

うまく行きました!ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問