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

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

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

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

Q&A

解決済

1回答

4402閲覧

pythonのtkで「command」で複数の関数を使いたい

退会済みユーザー

退会済みユーザー

総合スコア0

Python

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

0グッド

0クリップ

投稿2021/09/25 22:33

編集2021/09/25 23:44

前提・実現したいこと

pythonにあるtkでちょっとしたゲームを作ろうとしていました。「command」でappウィンドウとapp2ウィンドウどちらも消すを消すコマンドを打とうとしましたが、うまくいかず困っています。
なんとか完成させたいです。方法があるのならば教えてください。よろしくお願いいたします。

該当のソースコード

python

1import tkinter as tk 2 3def new_tk(): 4 app2 = tk.Tk() 5 but2 = tk.Button(text='quit',command="ここに二つのウィンドウを消すコマンド") 6 but2.place(x=100,y=200) 7 8app = tk.Tk 9but = tk.Button(text='new',command=new_tk) 10but.place(x=100,y=200) 11

試したこと

「def」コマンドを使って、複数の関数を一つの関数にまとめ、その関数を入れようとしましたが、「def」をどこに入れたらいいか分かりませんでした。最初に置いてもappとapp2が定義されておらず、importとdefの間に置いてもどちらも定義されておらず、defとappの間に置いてもappが定義されません。

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

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

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

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

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

Daregada

2021/09/25 23:22

「該当のソースコード」の内容が、1行目から間違っていて動作しない状態です。質問文に書くために実際のコードを簡略化したのであれば、簡略化したコードを一度実行して動くことを確かめてください。
退会済みユーザー

退会済みユーザー

2021/09/26 01:02 編集

失礼しました。tkinterと書くところ、tkinetrと書いておりました。すいません。
退会済みユーザー

退会済みユーザー

2021/09/25 23:42 編集

変えておきました。
guest

回答1

0

ベストアンサー

質問文のコードには複数の問題がありますが、おそらく実際のコードはこれと違っていて、質問に書かれた問題以外は動いているのでしょう。回答者は実際のコードを見ることができないのでわかりませんが。
補足: 削除線の部分は回答中に修正されました。

  • 先頭のtkinetrtkinterの誤り
  • 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で開くのが簡単です。

メインウィンドウが閉じるときにサブウィンドウが連動して閉じるため、but2commandには、メインウィンドウを閉じる関数オブジェクト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()

投稿2021/09/25 23:52

編集2021/09/27 03:35
Daregada

総合スコア11990

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

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

退会済みユーザー

退会済みユーザー

2021/09/26 01:07

回答ありがとうございました。but2はappの中でのボタンでOKです。 おかげで上手く動くようになりました。補足ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問