python
1...
2switch_button_image = tk.PhotoImage(file="./switch.png")
3button_Sw.configure(image=switch_button_image)
4...
tkinterのPhotoImageは「画像を表示しつづけている間、アプリケーションでPhotoImageインスタンスの参照をどこかにキープしておかなければならない」というちょっとわかりにくい仕様があったと思います。今のコードでインスタンスの参照を保持しているのはswitch_button_image変数ですが、この変数は__init__
メソッドのローカル変数なのでメソッド完了後はなくなってしまいます。つまりその時点でPhotoImageインスタンスの参照を保持している変数がなくなりtkinterが画像を表示する前提がくずれてしまうのではないかと想像します。
対処として
python
1...
2self.switch_button_image = tk.PhotoImage(file="./switch.png")
3button_Sw.configure(image=self.switch_button_image)
4...
のようにインスタンス変数に格納してはいかがでしょうか?
こうしておけばこのクラス(おそらくFrameの派生クラス)のインスタンスがなくならない限りPhotoImageインスタンスの参照がずっと残るので期待どおりに画像が表示されるのではないかと想像します。
すみませんが、今、自分で確認する時間がないので違ってたらごめんなさい。
追記:
実際にやってみましたが元の回答で書いたことは正しそうです。しかしながらご質問のコードは一部しか書かれておらず、書き方によって上記の問題以前にボタン自体が表示されないという不具合がおきそうです。以下のコードで確認してみました。
Python
1import tkinter as tk
2
3
4class MyFrame(tk.Frame):
5 # 問題とは無関係な冗長な記述をより短い記述に書き換えてます
6 def __init__(self, parent, controller):
7 tk.Frame.__init__(self, parent, bg='#014cc4')
8 self.controller = controller
9
10 switch_button_image = tk.PhotoImage(file="./switch.png")
11 button_Sw = tk.Button(self, image=switch_button_image, bg="white", width=40, height=40)
12 button_Sw.pack()
13 button_Sw.place(x=19, y=10)
14
15 setting_button_image = tk.PhotoImage(file="./setting.png")
16 button_Se = tk.Button(self, image=setting_button_image, bg="white", width=40, height=40)
17 button_Se.pack()
18 button_Se.place(x=250, y=10)
19
20
21def report(ev):
22 w = ev.widget
23 print(f'widget:{w}, width={w.winfo_width()}, height={w.winfo_height()}')
24
25
26root = tk.Tk()
27root.bind_all('<Configure>', report)
28root.geometry('400x400')
29frame = MyFrame(root, object())
30frame.pack()
31root.mainloop()
上記を実行するとMyFrameの大きさは1x1にしかならず、配置した2つのボタンはMyFrameの領域外に位置付けられてしまいボタン自体が見えなくなることがわかります。こうなる原因はウィジェットのレイアウト方法がおかしいからです。
MyFrameの画面構成を決めているのはMyFrameの__init__
メソッドですが、MyFrameのレイアウト方法は次のいずれかの方針とすべきです。(gridも選択肢になりますがその方法については言及しません)
(1) MyFrameの大きさを明示的に指定しておき、その上で各Buttonなどをplaceで配置
(2) 子供をpackで配置してMyFrameの大きさは子供の位置や大きさに応じて自動的に決める
元のコードでは(1),(2)のどちらでもなくpackとplaceを両方使ってます。placeを呼び出すとpackの効果はなくなりますのでpackしてないことと同義になります。
レイアウトのしかたは慣れないと混乱しがちです。例えば
http://www.shido.info/py/tkinter2.html
のような解説をよく読むとよいとおもいます。
「なぜうまくいかないか」について説明を試みましたがちょっと難しいかも知れませんので、最後に「うまく表示される簡単なコード例」を示しておきます。
python
1import tkinter as tk
2
3
4class MyFrame(tk.Frame):
5 def __init__(self, parent, controller):
6 # Frameのサイズを明示的に指定する
7 tk.Frame.__init__(self, parent, width=400, height=400, bg='#014cc4')
8 self.controller = controller
9
10 switch_button_image = tk.PhotoImage(file="./switch.png")
11 button_Sw = tk.Button(self, image=switch_button_image, bg="white", width=40, height=40)
12 button_Sw.place(x=19, y=10)
13 self.switch_button_image = switch_button_image # 画像インスタンスの参照を覚えておく
14
15 setting_button_image = tk.PhotoImage(file="./setting.png")
16 button_Se = tk.Button(self, image=setting_button_image, bg="white", width=40, height=40)
17 button_Se.place(x=250, y=10)
18 self.setting_button_image = setting_button_image # 画像インスタンスの参照を覚えておく
19
20
21root = tk.Tk()
22frame = MyFrame(root, object())
23frame.pack()
24root.mainloop()