tbsten
@tbsten (てべすてん)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

python tkinter 画像ボタンがうまく動作しない

Q&A

Closed

解決したいこと

python tkinterの質問です。
以下のコードを実行したところ画面に表示はされるのですが、ボタン1と2(bt1,bt2)に画像が表示されません。どうしてうまくいかないか、また、どうしたらうまくいくようになるかを教えてください。

フォルダ構成----------------------
python
+test.py
+add.png

test.py----------------------

import tkinter as tk
import time

root = tk.Tk()
root.title("Commander")

def myBtn(parent,text,command,img):
    im = tk.PhotoImage(file=img)
    time.sleep(2)
    ans = tk.Button(parent,text=text,command=command,image=im,compound="top")
    ans.pack(side=tk.LEFT)

    return ans 

def click1():
    print("1 clicked")
def click2():
    print("2 clicked")
def click3():
    print("3 clicked")

# 関数でボタン作成・追加
bt1 = myBtn(root,"その1",click1,"./add.png")
bt2 = myBtn(root,"その2",click2,"./add.png")
# そのまま書いてボタン作成・追加
im = tk.PhotoImage(file="./add.png")
bt3 = tk.Button(root,text="その3",command=click3,image=im,compound="top")
bt3.pack(side=tk.LEFT)


root.mainloop()

発生している問題・エラー

bt1,bt2のボタンに画像が表示されない。(bt3は表示されます)

自分で試したこと

ボタンをpackする順序を入れ替えたり、画像のパスを絶対パスにしたりしましたが、解決しませんでした。

0

1Answer

画像データがガベージコレクタに解放されてしまっているのだと思います。
以下のように、画像データを変数に入れて保持しておくと表示できるようです。

test.py
  import tkinter as tk
  import time

  root = tk.Tk()
  root.title("Commander")

  def myBtn(parent,text,command,img):
      im = tk.PhotoImage(file=img)
      time.sleep(2)
      ans = tk.Button(parent,text=text,command=command,image=im,compound="top")
      ans.pack(side=tk.LEFT)

-     return ans
+     return (ans, im)

  def click1():
      print("1 clicked")
  def click2():
      print("2 clicked")
  def click3():
      print("3 clicked")

  # 関数でボタン作成・追加
- bt1 = myBtn(root,"その1",click1,"./add.png")
+ bt1, im1 = myBtn(root,"その1",click1,"./add.png")
- bt2 = myBtn(root,"その2",click2,"./add.png")
+ bt2, im2 = myBtn(root,"その2",click2,"./add.png")
  # そのまま書いてボタン作成・追加
  im = tk.PhotoImage(file="./add.png")
  bt3 = tk.Button(root,text="その3",command=click3,image=im,compound="top")
  bt3.pack(side=tk.LEFT)


  root.mainloop()

0Like

Comments

  1. @tbsten

    Questioner

    ご回答ありがとうございます!
    まさかガーベジコレクタが関わっていたとは!
    ご回答謝様はreturnで画像データを返していらっしゃいますが、そのかわりに、グローバルなリストをあらかじめ作っておき、画像を読み込む度にリストに代入するといった方法でも問題はありませんか?
  2. グローバル変数に入れる方法でも大丈夫だと思います。
  3. @tbsten

    Questioner

    無事表示できました!ありがとうございました。

Your answer might help someone💌