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

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

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

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

Python

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

Q&A

解決済

1回答

589閲覧

pythonのtkinterボタンを押したときの関数の呼び出しができません。

tera877

総合スコア9

Tkinter

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

Python

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

0グッド

0クリップ

投稿2022/11/22 05:53

前提

pythonのtkinterで簡易的なタイピングゲームを作っています。
実行して遊び方のボタンをクリックしたら別のラベルを表示し、タイトルに戻るというボタンを押したら初期画面に戻るようにしたいです。そのため、タイトルに戻るボタンを押したら、commandでmain()という初期画面を設定している画面に変更する関数を呼び出そうとしているのですが、呼び出せません。

実現したいこと

タイトルに戻るというボタンを押したら初期画面に戻り、それを何回でも続けられるようにしたいです。

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

Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\nonch\AppData\Local\Programs\Thonny\lib\tkinter_init_.py", line 1705, in call
return self.func(*args)
File "C:\Users\nonch\Documents\pythonフォルダー\keses.py", line 74, in main
title_label.pack(ipady=60)
File "C:\Users\nonch\AppData\Local\Programs\Thonny\lib\tkinter_init_.py", line 2143, in pack_configure
+ self._options(cnf, kw))
_tkinter.TclError: bad window path name ".!label7"

該当のソースコード

python

import tkinter as tk

root = tk.Tk()
root.geometry("1200x600")
root.title("タイピングゲーム")

words = ["ishikawa", "kanazawa", "hokuriku","nagano"]

index = 0
number_of_words = 0

#関数内で使うグローバル変数
word_label = tk.Label(text=words[index], foreground="#66CCFF", font=("",50))
ans_label = tk.Label(text="", font=("",60)) #キー入力の受け取り

count_label = tk.Label(text=4, font=("",100)) #スタートカウントダウンの消去
time_left_label = tk.Label(text="残り時間: 秒", font=("",20))
timer_label = tk.Label(text=31, font=("",20))
number_of_words_label = tk.Label(text=f"タイプワード数:{number_of_words}", font=("",20))

num = 4
timer_num = 31

#####タイプ画面#####
def create_widgets():
word_label.pack(ipady=100)
ans_label.pack()
time_left_label.place(x=0, y=0)
timer_label.place(x=140, y=0)
number_of_words_label.place(x=0, y=50)
timer()

def timer():
global timer_num
if timer_num == timer_label["text"]:
timer_num -= 1
timer_label.configure(text=timer_num)
if timer_num > 0:
root.after(1000, timer)

#####カウントダウンとウィジェットの消去#####
def countdown():
start_button.destroy()
title_label.destroy()
rule_button.destroy()
count_label.pack(expand=True)
global num
if num == count_label["text"]:
num -= 1
count_label.configure(text=num)
if num > 0:
root.after(1000, countdown)

elif num == 0: count_label.destroy() create_widgets()

#####遊び方#####
def rule():
rule_label.pack(ipady=60)
title_label.destroy()
rule_button.destroy()
start_button.destroy()
return_button.pack()

title_label = tk.Label(text="タイピングゲーム", font=("",50)) #グローバル変数として定義しないと関数内で消去できない
rule_button = tk.Button(text="遊び方", font=("",30), command=rule)
start_button = tk.Button(text="スタート", font=("",30), command=countdown)
def main():
#####初期画面#####
#title_label = tk.Label(text="タイピングゲーム", font=("",50)) #グローバル変数として定義しないと関数内で消去できない
title_label.pack(ipady=60)
#rule_button = tk.Button(text="遊び方", font=("",30), command=rule)
rule_button.place(x=750, y=300)
#start_button = tk.Button(text="スタート", font=("",30), command=countdown)
start_button.place(x=250, y=300)

main()

rule_label = tk.Label(text="~遊び方~", font=("",50))
return_button = tk.Button(text="タイトルに戻る", font=("",30), command=main)

#####キー入力#####
def type_event(event):
global index
global number_of_words
ans_label["text"] += event.keysym
if ans_label["text"] == word_label["text"]:
ans_label.configure(text="")
index += 1
word_label.configure(text=words[index])
number_of_words += 1
number_of_words_label.configure(text=f"タイプワード数:{number_of_words}")

elif event.keysym == "BackSpace": text = ans_label["text"] ans_label["text"] = text[:-10]

root.bind("<KeyPress>", type_event) #関数とキー入力の紐づけ

root.mainloop()

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

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

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

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

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

teamikl

2022/11/22 07:59

コードを実行して見ないと問題解決が難しい場合もあるので、 コードは、markdown 記法のコード導入内に記載してください。 Python のコードはインデント情報が失われてしまいます。
guest

回答1

0

ベストアンサー

エラーメッセージからの推測ですが、
ウィジェットが破棄(destroy) されている為、
再度の配置 packや place は出来ません。

表示非表示の切り替えは、pack/pack_forget を用います。
place で配置の場合は place_forget。

多くのウィジェットを個別に表示非表示切り替えは大変なので、
タイトル画面と遊び方画面をそれぞれ別のFrame に配置し、
親ウィジェットとなるFrameの表示切替で対応できます。

他には、Frame をレイヤーの様に重ねて、
上に持ってくるFrameを切り替える実装方法もあります。
詳しくは、「画面遷移」等をキーワードに調べて見て下さい。

投稿2022/11/22 07:55

teamikl

総合スコア8664

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

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

tera877

2022/11/22 08:15

ご指摘いただいた部分を修正したらしっかりと動作しました。ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問