Toplevelを継承したときに、意図した動作をしません。
Frameを継承したら、意図した動作になりました。
Toplevelを継承した際の書き方の問題だと思いますが、どう直せばいいか教えてください。
意図した動作としては、tk.Tk()とtk.Toplevel()のウィンドウを1つずつ表示することです。
実際の動作としては、小さいウィンドウが2つ余計に出てきます。title()が自分では設定していない"tk"となっていて原因が分かりません。
回答よろしくお願いします。
意図した動作をしない
Python
1from tkinter import ttk 2import tkinter as tk 3 4class Main(tk.Tk): 5 def __init__(self): 6 self.sub = Sub() 7 self.open() 8 def open(self): 9 super().__init__() 10 self.geometry("400x300+0+0") 11 self.title("main") 12 self.sub.open(self) 13 14class Sub(tk.Toplevel): 15 def open(self, master): 16 super().__init__() 17 self.geometry("200x200+25+25") 18 self.title("sub") 19 self.attributes("-topmost", True) 20 self.grab_set() 21 self.transient(master) 22 self.protocol("WM_DELETE_WINDOW", self.close) 23 24 def close(self): 25 self.grab_release() 26 self.destroy() 27 28def main(): 29 app = Main() 30 app.mainloop() 31 32if __name__ == "__main__": 33 main()
Frame継承だと意図した動作
Python:
1from tkinter import ttk 2import tkinter as tk 3 4class Main(tk.Tk): 5 def __init__(self): 6 super().__init__() 7 self.geometry("400x300+0+0") 8 self.title("main") 9 sub = Sub() 10 sub.open(self) 11 12class Sub(tk.Frame): 13 def open(self, master): 14 self.tl = tk.Toplevel() 15 super().__init__(self.tl) 16 self.tl.geometry("200x200+25+25") 17 self.tl.title("sub") 18 self.tl.attributes("-topmost", True) 19 self.tl.grab_set() 20 self.tl.transient(master) 21 self.tl.protocol("WM_DELETE_WINDOW", self.close) 22 23 def close(self): 24 self.tl.grab_release() 25 self.tl.destroy() 26 27def main(): 28 app = Main() 29 app.mainloop() 30 31if __name__ == "__main__": 32 main()
追記
teamikl様より修正して意図した結果になったソースコード
Python:
1from tkinter import ttk 2import tkinter as tk 3 4class Main(tk.Tk): 5 def __init__(self): 6 super().__init__() 7 self.sub = Sub() 8 self.geometry("400x300+0+0") 9 self.title("main") 10 self.sub.open(self) # ← 書かなくてもToplevelウィンドウが表示される(?) 11 12class Sub(tk.Toplevel): 13 def open(self, master): 14 self.geometry("200x200+25+25") 15 self.title("sub") 16 self.attributes("-topmost", True) 17 self.grab_set() 18 self.transient(master) 19 self.protocol("WM_DELETE_WINDOW", self.close) 20 21 def close(self): 22 self.grab_release() 23 self.destroy() 24 25def main(): 26 app = Main() 27 app.mainloop() 28 29if __name__ == "__main__": 30 main()
ボタン押下でToplevelを開くように個人的に変えたプログラム
Python:
1from tkinter import ttk 2import tkinter as tk 3 4""" 5 Frame を継承するのが一般的(?)だが、 6 Frame を生成・配置する必要はないので、Tk を継承する 7""" 8class Main(tk.Tk): 9 def __init__(self): 10 # Tk のコンストラクタ呼び出し 11 super().__init__() 12 # Sub のインスタンス生成(ここではToplevelウィンドウは表示しない) 13 self.sub = Sub() 14 # Tk の設定 15 self.geometry("400x300+0+0") 16 self.title("main") 17 # Tk にウィジェット配置 18 self.button = ttk.Button(self, text="open", command=self.pushed) 19 self.button.grid() 20 21 def pushed(self): 22 # open 呼び出しにより、Toplevelウィンドウを生成 23 self.sub.open(self) 24 25class Sub(tk.Toplevel): 26 """ 27 継承先クラス Sub のコンストラクタ __init__() の定義が無いと、 28 Sub() インスタンス生成時に継承元クラス Toplevel のコンストラクタ __init__() が呼ばれる。 29 Sub() インスタンス生成時に継承元のコンストラクタが呼ばれると困るので、 30 コンストラクタ(処理としては「何もしない」)を定義する。 31 32 上記対応により継承元のコンストラクタを呼ばなくなったため、 33 super().__init__() を別の関数(open)に書くことで、 34 そのタイミングで継承元のコンストラクタを呼び出す。 35 """ 36 def __init__(self): 37 pass 38 def open(self, master): 39 # Toplevel のコンストラクタ呼び出し(ここでToplevelウィンドウを表示する) 40 super().__init__() 41 # Toplevel の設定 42 self.geometry("200x200+25+25") 43 self.title("sub") 44 self.attributes("-topmost", True) 45 self.grab_set() 46 self.transient(master) 47 self.focus_set() 48 self.protocol("WM_DELETE_WINDOW", self.close) 49 50 def close(self): 51 self.grab_release() 52 self.destroy() 53 54def main(): 55 app = Main() 56 app.mainloop() 57 58if __name__ == "__main__": 59 main()
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/01/13 04:29
2021/01/13 04:50 編集
2021/01/17 07:51
2021/01/18 04:47
2021/01/18 05:18 編集
2021/01/19 00:01
2021/01/19 01:18
2021/01/19 01:55 編集
2021/01/19 05:22
2021/01/19 07:33