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

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

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

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

Python

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

Q&A

1回答

1046閲覧

pythonのtkinterでタイピングゲームを作っています。after_cancel()の使い方を教えてほしいです。

tera877

総合スコア9

Tkinter

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

Python

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

0グッド

0クリップ

投稿2022/11/28 15:53

編集2022/11/29 15:38

前提

pythonのtkinterで簡易的なタイピングゲームを作っています。timer()という関数内でafterを使っています。そのafterが動いている最中にウインドウを閉じると、エラーが発生します。

実現したいこと

このエラーをなくすために、afterが動いている最中にウインドウを閉じたときのafterの処理をキャンセルするafter_cancel()の使い方を教えてほしいです。

発生している問題・エラーメッセージ

invalid command name "55043336countdown" while executing "55043336countdown" ("after" script)

該当のソースコード

python

1import tkinter as tk 2import random 3 4root = tk.Tk() 5root.geometry("1200x600") 6root.title("タイピングゲーム") 7 8words1 = ["オムライス", "流れ星", "おままごと", "チワワ", "オーストリア", "ベット", 9 "バスタオル", "日焼け止め", "パパイヤ", "みそ汁" ,"マグロ", "落ち葉", 10 "七夕", "クリーム", "空手", "蝶", "アルバイト", "桃アイス", 11 "イチゴ", "タヌキ", "キャベツ", "ごみ箱", "おしぼり", "ヘルメット", 12 "ラクダ", "ファイル", "薬", "メガネ", "つめ切り", "パスタ"] 13words2 = ["omuraisu", "nagarebosi", "omamagoto", "tiwawa", "o-sutoria", "betto", 14 "basutaoru", "hiyakedome", "papaiya", "misosiru", "maguro", "otiba", 15 "tanabata", "kuri-mu", "karate", "tyou", "arubaito", "momoaisu", 16 "itigo", "tanuki", "kyabetu", "gomibako", "osibori", "herumetto", 17 "rakuda", "fairu", "kusuri", "megane", "tumekiri", "pasuta"] 18 19num_list = random.sample(range(30), 30) #乱数リスト 20index = 0 21count_num = 4 #スタートのカウントダウン 22timer_num = 31 #残り時間 23word_count = 0 #タイプワード数 24 25word_label1 = tk.Label(text=words1[num_list[index]], foreground="#66CCFF", font=("",40)) #平仮名 26word_label2 = tk.Label(text=words2[num_list[index]], foreground="#66CCFF", font=("",40)) #ローマ字 27ans_label = tk.Label(text="", font=("",60)) #キー入力の受け取り 28time_left_label = tk.Label(text="残り時間: 秒", font=("",20)) #残り時間 29timer_label = tk.Label(text=31, font=("",20)) 30word_count_label = tk.Label(text=f"タイプワード数:{word_count}", font=("",20)) 31end_label = tk.Label(text="終了!!", font=("",50)) #終了画面 32score_label = tk.Label(text=f"あなたのタイプワード数は{word_count}です", font=("",30)) #スコア 33count_label = tk.Label(text=4, font=("",100)) #スタートのカウントダウン 34rule_label = tk.Label(text="スタートボタンを押すとカウントダウンが始まります。\ 35\nゲームが始まると、タイプワードが表示されるので、タイピングを始めてください。\n\n \ 36ヒントとしてローマ字表記のお題が表示されていますが、\n打ち込んだローマ字と異なっていてもタイプワードが打ち込めていれば大丈夫です。", font=("",20)) 37hint_label = tk.Label(text = "例: nagarebosi → nagareboshi \nどちらでもok", font=("",40)) 38 39#####初期画面##### 40def main(): 41 title_label.pack(pady=60) 42 rule_button.place(x=750, y=300) 43 start_button.place(x=250, y=300) 44 45 return_button.pack_forget() #タイトルに戻るボタンの非表示 46 rule_label.pack_forget() 47 end_label.pack_forget() 48 score_label.pack_forget() 49 end_button.pack_forget() 50 hint_label.pack_forget() 51 52 global word_count 53 global timer_num 54 global index 55 global num_list 56 57 word_count = 0 58 word_count_label.configure(text=f"タイプワード数:{word_count}") 59 ans_label.configure(text="") 60 timer_num = 31 61 timer_label.configure(text=31) 62 index = 0 63 64#####タイプ画面##### 65def type_screen(): 66 word_label1.pack(pady=60) 67 word_label2.pack() 68 ans_label.pack(pady=40) 69 time_left_label.place(x=0, y=0) 70 timer_label.place(x=140, y=0) 71 word_count_label.place(x=0, y=50) 72 73 timer() 74 75#####残り時間の表示と終了時の関数呼び出し##### 76def timer(): 77 global timer_num 78 79 if timer_num == timer_label["text"]: 80 timer_num -= 1 81 timer_label.configure(text=timer_num) 82 83 if timer_num > 0: 84 root.after(1000, timer) 85 86 elif timer_num == 0: 87 timer_label.place_forget() 88 end() 89 90#####終了時の間数##### 91def end(): 92 word_label1.pack_forget() 93 word_label2.pack_forget() 94 ans_label.pack_forget() 95 time_left_label.place_forget() 96 #timer_label.place_forget() 97 word_count_label.place_forget() #タイプ画面のウィジェットの非表示 98 99 end_label.pack(pady=60) 100 score_label.pack(pady=30) 101 end_button.pack(pady=10) 102 num_list = random.sample(range(24), 24) #乱数リスト 103 104#####スタートのカウントダウン##### 105def countdown(): 106 start_button.place_forget() 107 title_label.pack_forget() 108 rule_button.place_forget() #初期画面の非表示 109 110 count_label.pack(expand=True) 111 global count_num 112 113 if count_num == count_label["text"]: 114 count_num -= 1 115 count_label.configure(text=count_num) 116 117 if count_num > 0: 118 root.after(1000, countdown) 119 120 elif count_num == 0: 121 count_label.pack_forget() 122 count_num = 4 123 count_label.configure(text=count_num) 124 type_screen() 125 126#####遊び方の説明画面##### 127def rule(): 128 start_button.place_forget() 129 title_label.pack_forget() 130 rule_button.place_forget() #初期画面の非表示 131 132 rule_label.pack(pady=20) 133 hint_label.pack(pady=20) 134 return_button.pack(pady= 30) 135 136title_label = tk.Label(text="タイピングゲーム", font=("",50)) #タイトル 137rule_button = tk.Button(text="遊び方", font=("",30), command=rule) #遊び方ボタン 138start_button = tk.Button(text="スタート", font=("",30), command=countdown) #スタートボタン 139return_button = tk.Button(text="タイトルに戻る", font=("",30), command=main) #タイトルに戻るボタン 140end_button = tk.Button(text="タイトルに戻る", font=("",30), command=main) 141 142def type_setting(): 143 global word_count 144 global index 145 ans_label.configure(text="") 146 word_count += 1 147 index += 1 148 word_label1.configure(text=words1[num_list[index]]) 149 word_label2.configure(text=words2[num_list[index]]) 150 word_count_label.configure(text=f"タイプワード数:{word_count}") 151 152#####キー入力##### 153def type_event(event): 154 global index 155 global word_count 156 text = ans_label["text"] 157 length = len(event.keysym) #入力キーの文字数 158 159 if event.keysym == "BackSpace": 160 ans_label["text"] = text[:-1] 161 162 elif event.keysym == "minus": 163 ans_label["text"] += "-" 164 165 elif length >= 2: 166 ans_label["text"] += "" 167 168 else: 169 ans_label["text"] += event.keysym 170 171 if ans_label["text"] == word_label2["text"]: 172 type_setting() 173 174 elif word_label2["text"] == "nagarebosi": 175 if ans_label["text"] == "nagareboci" or ans_label["text"] == "nagareboshi": 176 type_setting() 177 178 elif word_label2["text"] == "betto": 179 if ans_label["text"] == "bextuto" or ans_label["text"] == "beltuto": 180 type_setting() 181 182 elif word_label2["text"] == "misosiru": 183 if ans_label["text"] == "misociru" or ans_label["text"] == "misoshiru": 184 type_setting() 185 186 elif word_label2["text"] == "otiba": 187 if ans_label["text"] == "ochiba": 188 type_setting() 189 190 elif word_label2["text"] == "kuri-mu": 191 if ans_label["text"] == "curi-mu": 192 type_setting() 193 194 elif word_label2["text"] == "karate": 195 if ans_label["text"] == "carate": 196 type_setting() 197 198 elif word_label2["text"] == "tyou": 199 if ans_label["text"] == "tilyou" or ans_label["text"] == "tixyou": 200 type_setting() 201 202 elif word_label2["text"] == "itigo": 203 if ans_label["text"] == "ichigo": 204 type_setting() 205 206 elif word_label2["text"] == "kyabetu": 207 if ans_label["text"] == "kilyabetu" or ans_label["text"] == "kixyabetu": 208 type_setting() 209 210 elif word_label2["text"] == "gomibako": 211 if ans_label["text"] == "gomibaco": 212 type_setting() 213 214 elif word_label2["text"] == "osibori": 215 if ans_label["text"] == "oshibori" or ans_label["text"] == "ocibori": 216 type_setting() 217 218 elif word_label2["text"] == "herumetto": 219 if ans_label["text"] == "herumextuto" or ans_label["text"] == "herumeltuto": 220 type_setting() 221 222 elif word_label2["text"] == "fairu": 223 if ans_label["text"] == "fulairu" or ans_label["text"] == "hulairu": 224 type_setting() 225 226 elif word_label2["text"] == "kusuri": 227 if ans_label["text"] == "cusuri": 228 type_setting() 229 230 if word_count >= 20: 231 score_label.configure(text=f"あなたのタイプワード数は{word_count}で、点数は100点です!\n達人レベルのタイピング力を持っています!") 232 233 elif word_count >= 15: 234 score_label.configure(text=f"あなたのタイプワード数は{word_count}で、点数は80点です!") 235 236 elif word_count >= 10: 237 score_label.configure(text=f"あなたのタイプワード数は{word_count}で、点数は60点です!") 238 239 elif word_count >= 5: 240 score_label.configure(text=f"あなたのタイプワード数は{word_count}で、点数は40点です!") 241 242 elif word_count < 5: 243 score_label.configure(text=f"あなたのタイプワード数は{word_count}で、点数は20点です!") 244 245root.bind("<KeyPress>", type_event) #関数とキー入力の紐づけ 246 247main() #初期画面の表示 248 249root.mainloop()

試したこと

補足情報(FW/ツールのバージョンなど)

エラーコードは読めないですが、timer()という関数のところで、1秒処理を遅らせるafterを使っていて、きっとそれのことを言われているのだと思います。

エラーが毎回出るわけではなく、私も正直いつ出るのかわかりません。

おそらくですが、実行してからウインドウが開き、そのままもう一度実行をします。その後にtimer関数が動いている、ゲーム開始時のカウントダウン中にウインドウを閉じるとエラーが発生します。なので、本来の処理にはあまり関係ないような気がしますが、気になったのでわかる方がいたら教えていただきたいです。

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

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

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

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

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

guest

回答1

0

ゲーム開始時のカウントダウン中にウインドウを閉じるとエラーが発生します。

after関数で登録されたタスクはウィンドウを消しても消滅しません。なのでdestroy()後にスケジュールされたタスクを実行しようとしてエラーが発生します。なのでウィンドウを閉じる時にタスクが残っていないか確認し、残っていた場合は先にafter_cancel()でタスクを取り消す必要があります。
https://stackoverflow-com.translate.goog/questions/26168967/invalid-command-name-while-executing-after-script?_x_tr_sl=en&_x_tr_tl=ja&_x_tr_hl=ja&_x_tr_pto=sc

過去の類似質問が見つかりました。こちらの回答が参考になると思います。

×押したときに特定の処理を走らせる方法(類似質問のリンクで解説されてんだけどな…)
https://imagingsolution.net/program/python/tkinter/confirmation_x_button/
after_cancelの使い方
https://office54.net/python/tkinter/after-method-schedule

投稿2022/11/29 02:09

編集2022/11/29 06:38
pig_vba

総合スコア807

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問