質問文のコードには複数の問題がありますが、おそらく実際のコードはこれと違っていて、質問に書かれた問題以外は動いているのでしょう。回答者は実際のコードを見ることができないのでわかりませんが。
補足: 削除線の部分は回答中に修正されました。
先頭のtkinetr
はtkinter
の誤り
place
で各ボタンの位置を(100, 200)に設定しているが、tkinterで生成されるウィンドウのサイズの初期値は200x200なので、ボタンがウィンドウ内に表示されない
ボタンのテキストを設定するオプション引数はtext
であって、label
ではない
app
に対してmainloop
を呼び出していないため、メインウィンドウが表示されない。
これらを修正すると、質問文のコードが動くようになり、質問の状況が再現できます。
さて、あなたが作ろうとしている「2つのウィンドウを閉じる」関数に必要なのは、
- メインウィンドウのウィジェットオブジェクト
- サブウィンドウのウィジェットオブジェクト
の2つです。どちらも、tk.Tk()
で生成されます。
メインウィンドウのウィジェットオブジェクトを利用するには、変数app
にそれが代入された後に関数を書く必要があります。変数app
はグローバル変数なので、代入後はどこでもその内容を参照できます。
また、mainloop
でイベントループを開始すると、それより後の内容はイベントループの終了後(ウィンドウを閉じた後)にならないと実行されないため、mainloop
よりも前に関数を書く必要があります。さもないと、but2
のボタンを押したときに、関数が未定義だというエラーが出ます。
サブウィンドウのほうはちょっと複雑です。
サブウィンドウのウィジェットオブジェクトを利用するには、変数app2
にそれが代入された後である必要があります。ここで、変数app2
は関数new_tk
内でのみ有効なローカル変数なので、関数new_tk
の処理から抜けると使えなくなります。
すると、変数app2
だけが使っていたウィジェットオブジェクトはガベージコレクションにより自動的に削除されてしまいます。
これを避けるには、サブウィンドウもメインウィンドウと同様に関数の外側で生成してグローバル変数に入れる(あなたが自分で作るならこちらがわかりやすいでしょう)か、変数app2
以外にもサブウィンドウのウィジェットオブジェクトへの参照を作ります。
以下のコードでは、lambda
という機能を使い、lambda
の引数x
に変数app2
の値(ウィジェットオブジェクトのID)を代入することで、ガベージコレクションによる自動的な削除を回避しています。
そして、but2
のボタンを押すと、その引数x
を指定した関数my_close
を呼び出し、そこでサブウィンドウとメインウィンドウをそれぞれdestroy
しています。
Python
1import tkinter as tk
2
3
4def new_tk():
5 app2 = tk.Tk()
6 but2 = tk.Button(text='quit', command=lambda x=app2: my_close(x))
7 but2.place(x=100, y=100)
8
9
10app = tk.Tk()
11but = tk.Button(text='new', command=new_tk)
12but.place(x=100, y=100)
13
14
15def my_close(target):
16 target.destroy()
17 app.destroy()
18
19
20app.mainloop()
作っていてどちらを意図しているのかわからないのでそのままにしてありますが、but2
をサブウィンドウに表示したいのであれば、以下のように修正してください。
diff
1- but2 = tk.Button(text='quit', command=lambda x=app2: my_close(x))
2+ but2 = tk.Button(app2, text='quit', command=lambda x=app2: my_close(x))
補足: 今回は
pythonのtkで「command」で複数の関数を使いたい
という質問だったので、それに沿った回答になりましたが、「サブウィンドウをメインウィンドウと連動させて閉じたい」というだけなら、サブウィンドウをToplevel
で開くのが簡単です。
メインウィンドウが閉じるときにサブウィンドウが連動して閉じるため、but2
のcommand
には、メインウィンドウを閉じる関数オブジェクトapp.destroy
だけを指定すれば事足ります。
Python
1import tkinter as tk
2
3
4def new_tk():
5 tk.Toplevel()
6 but2 = tk.Button(text='quit', command=app.destroy)
7 but2.place(x=100, y=100)
8
9
10app = tk.Tk()
11but = tk.Button(text='new', command=new_tk)
12but.place(x=100, y=100)
13
14app.mainloop()