Tkinter开发剪刀石头布游戏时reset按钮报bad window path name错误求助
错误信息
点击reset按钮时触发如下错误:
Traceback (most recent call last):
File "C:\Python36\lib\tkinter_init_.py", line 1699, in call
return self.func(*args)
File "c:/Users/---------/OneDrive - -------------/python/rock paper scissors.py", line 26, in reset
run()
File "c:/Users/-----------/OneDrive - ---------------/python/rock paper scissors.py", line 186, in run
choose_player_number()
File "c:/Users/--------------/OneDrive - -----------------/python/rock paper scissors.py", line 181, in choose_player_number
one_player.grid(column= 2, row=1)
File "C:\Python36\lib\tkinter_init_.py", line 2220, in grid_configure
+ self._options(cnf, kw))
_tkinter.TclError: bad window path name ".!button5"
原代码
import random import tkinter as tk from tkinter import * window = tk.Tk() window.geometry("1400x860") window.title = "Rock paper scissors" result = Label(window, text= "result will appear here", bg="green") player_number = "" list_of_integers = ["1", "2", "3"] title = Label(window, text = "Rock paper scissors" , bg= "blue", fg = "white", font= "Times") title.grid(column=3, row=0) def reset(): filler.destroy filler2.destroy filler3.destroy title.destroy result.destroy rock.destroy paper.destroy scissors.destroy reset1.destroy run() reset1 = Button(window, text = "Reset", command= reset, fg="blue", bg = "yellow") def evaluate_rock(): global computer_input if computer_input == "3": win() elif computer_input == "2": loose() else: draw() def evaluate_scissors(): global computer_input if computer_input == "2": win() elif computer_input == "1": loose() else: draw() def evaluate_paper(): global computer_input if computer_input == "1": win() elif computer_input == "3": loose() else: draw() def computer_choice(input): global computer_input computer_input = random.choice(list_of_integers) if computer_input == "1": computer_value = "Rock" elif computer_input == "2": computer_value = "paper" else: computer_value = "scissors" computer_result = Label(window, text= "the computer's choice was: " + computer_value , fg = "blue", bg = "green") computer_result.grid(column=3, row=3) if input == "rock": evaluate_rock() elif input == "scissors": evaluate_scissors() else: evaluate_paper() return computer_input rock = Button(window, text="Rock", command= lambda: computer_choice("rock"), fg="green", bg="blue") scissors = Button(window, text="Scissors", command = lambda: computer_choice("scissors"), fg = "black", bg = "blue") paper = Button(window, text="paper", command = lambda: computer_choice("paper"), fg = "green", bg = "blue") player_1 = Label(window, text = "Player 1", fg = "blue", bg = "red") player_2 = Label(window, text= "Player 2", fg= "blue", bg= "red") def evaluate(): if player1input == player2input: result.configure(text= "Draw") elif player1input == "rock" and player2input == "scissors": result.configure(text= "Player 1 wins") elif player1input == "rock" and player2input == "paper": result.configure(text= "player 2 wins") elif player2input == "rock" and player1input == "scissors": result.configure(text= "Player 2 wins") elif player2input == "rock" and player1input == "paper": result.configure(text= "Player 1 wins") elif player1input == "paper" and player2input == "scissors": result.configure(text= "player 2 wins") elif player2input == "paper" and player1input == "scissors": result.configure(text= "Player 1 wins") reset1.grid(column= 3, row= 5) def player_2_input(p2i): global player2input player2input = p2i rock.destroy paper.destroy scissors.destroy player_2.destroy evaluate() return player2input def player2(): player_1.destroy player_2.grid(column= 3, row= 2) rock.configure(command = lambda: player_2_input("rock")) paper.configure(command= lambda: player_2_input("paper")) scissors.configure(command= lambda: player_2_input("scissors")) def player_1_input(p1i): global player1input player1input = p1i player2() return player1input def win(): result.configure(text= "You Win") reset1.grid(column= 3, row= 5) def loose(): result.configure(text= "You loose") reset1.grid(column= 3, row= 5) def draw(): result.configure(text= "Draw") reset1.grid(column= 3, row= 5) def place_buttons(): result.grid(column=3, row=1) if player_number == 1: rock.grid(column=2, row=2) scissors.grid(column = 4, row=2) paper.grid(column = 3, row=2) elif player_number == 2: player_1.grid(column= 3, row= 2) rock.configure(command = lambda: player_1_input("rock")) paper.configure(command= lambda: player_1_input("paper")) scissors.configure(command= lambda: player_1_input("scissors")) rock.grid(column=2, row=3) scissors.grid(column = 4, row=3) paper.grid(column = 3, row=3) one_player = Button(window, text = "One Player", command = lambda: [oneplayer(), place_buttons()]) two_players = Button(window, text= "Two players", command = lambda: [twoplayers(), place_buttons()]) def oneplayer(): title.configure(text = "One player") title.grid(column=3, row=0) global player_number player_number = 1 one_player.destroy() two_players.destroy() def twoplayers(): title.configure(text = "Two players") title.grid(column=3, row=0) global player_number player_number = 2 one_player.destroy() two_players.destroy() def add_fillers(): global filler filler = Label(window, text = " ") filler.grid(column=1, row=0) global filler2 filler2 = Label(window, text = " ") filler2.grid(column=0, row=0) global filler3 filler3 = Label(window, text = " ") filler3.grid(column=2, row=0) def choose_player_number(): one_player.grid(column= 2, row=1) two_players.grid(column= 4, row=1) def run(): add_fillers() choose_player_number() run() window.mainloop()
问题根源
- 按钮被永久销毁:
oneplayer()和twoplayers()中调用one_player.destroy()、two_players.destroy(),彻底删除了按钮对象,Reset后run()试图重新布局已销毁的按钮,触发错误。 - destroy方法调用错误:所有
xxx.destroy缺少括号,组件未被真正销毁,残留组件干扰界面重建。 - 临时组件未清理:每次游戏生成的
computer_result标签未在Reset时清理,导致界面堆积。
修复方案
1. 用grid_remove()替代destroy()保留组件
将one_player.destroy()、two_players.destroy()改为one_player.grid_remove()、two_players.grid_remove(),仅隐藏按钮而非永久销毁,后续可重新显示。
2. 修正destroy方法的语法错误
所有xxx.destroy改为xxx.destroy(),确保组件被正确销毁。
3. 清理临时生成的组件
在reset()函数中遍历窗口子组件,销毁computer_result这类动态生成的标签:
for widget in window.winfo_children(): if isinstance(widget, Label) and widget.cget("text").startswith("the computer's choice was:"): widget.destroy()
4. 调整Reset逻辑,改用隐藏核心组件
将核心组件(如title、result)的销毁改为隐藏,避免重复创建对象,减少资源消耗。
修复后的完整代码
import random import tkinter as tk from tkinter import * window = tk.Tk() window.geometry("1400x860") window.title = "Rock paper scissors" result = Label(window, text= "result will appear here", bg="green") player_number = "" list_of_integers = ["1", "2", "3"] title = Label(window, text = "Rock paper scissors" , bg= "blue", fg = "white", font= "Times") title.grid(column=3, row=0) def reset(): # 清理临时生成的电脑选择标签 for widget in window.winfo_children(): if isinstance(widget, Label) and widget.cget("text").startswith("the computer's choice was:"): widget.destroy() # 隐藏所有核心组件 filler.grid_remove() filler2.grid_remove() filler3.grid_remove() title.grid_remove() result.grid_remove() rock.grid_remove() paper.grid_remove() scissors.grid_remove() reset1.grid_remove() player_1.grid_remove() player_2.grid_remove() run() reset1 = Button(window, text = "Reset", command= reset, fg="blue", bg = "yellow") def evaluate_rock(): global computer_input if computer_input == "3": win() elif computer_input == "2": loose() else: draw() def evaluate_scissors(): global computer_input if computer_input == "2": win() elif computer_input == "1": loose() else: draw() def evaluate_paper(): global computer_input if computer_input == "1": win() elif computer_input == "3": loose() else: draw() def computer_choice(input): global computer_input computer_input = random.choice(list_of_integers) if computer_input == "1": computer_value = "Rock" elif computer_input == "2": computer_value = "paper" else: computer_value = "scissors" computer_result = Label(window, text= "the computer's choice was: " + computer_value , fg = "blue", bg = "green") computer_result.grid(column=3, row=3) if input == "rock": evaluate_rock() elif input == "scissors": evaluate_scissors() else: evaluate_paper() return computer_input rock = Button(window, text="Rock", command= lambda: computer_choice("rock"), fg="green", bg="blue") scissors = Button(window, text="Scissors", command = lambda: computer_choice("scissors"), fg = "black", bg = "blue") paper = Button(window, text="paper", command = lambda: computer_choice("paper"), fg = "green", bg = "blue") player_1 = Label(window, text = "Player 1", fg = "blue", bg = "red") player_2 = Label(window, text= "Player 2", fg= "blue", bg= "red") def evaluate(): if player1input == player2input: result.configure(text= "Draw") elif player1input == "rock" and player2input == "scissors": result.configure(text= "Player 1 wins") elif player1input == "rock" and player2input == "paper": result.configure(text= "player 2 wins") elif player2input == "rock" and player1input == "scissors": result.configure(text= "Player 2 wins") elif player2input == "rock" and player1input == "paper": result.configure(text= "Player 1 wins") elif player1input == "paper" and player2input == "scissors": result.configure(text= "player 2 wins") elif player2input == "paper" and player1input == "scissors": result.configure(text= "Player 1 wins") reset1.grid(column= 3, row= 5) def player_2_input(p2i): global player2input player2input = p2i rock.grid_remove() paper.grid_remove() scissors.grid_remove() player_2.grid_remove() evaluate() return player2input def player2(): player_1.grid_remove() player_2.grid(column= 3, row= 2) rock.configure(command = lambda: player_2_input("rock")) paper.configure(command= lambda: player_2_input("paper")) scissors.configure(command= lambda: player_2_input("scissors")) def player_1_input(p1i): global player1input player1input = p1i player2() return player1input def win(): result.configure(text= "You Win") reset1.grid(column= 3, row= 5) def loose(): result.configure(text= "You loose") reset1.grid(column= 3, row= 5) def draw(): result.configure(text= "Draw") reset1.grid(column= 3, row= 5) def place_buttons(): result.grid(column=3, row=1) if player_number == 1: rock.grid(column=2, row=2) scissors.grid(column = 4, row=2) paper.grid(column = 3, row=2) elif player_number == 2: player_1.grid(column= 3, row= 2) rock.configure(command = lambda: player_1_input("rock")) paper.configure(command= lambda: player_1_input("paper")) scissors.configure(command= lambda: player_1_input("scissors")) rock.grid(column=2, row=3) scissors.grid(column = 4, row=3) paper.grid(column = 3, row=3) one_player = Button(window, text = "One Player", command = lambda: [oneplayer(), place_buttons()]) two_players = Button(window, text= "Two players", command = lambda: [twoplayers(), place_buttons()]) def oneplayer(): title.configure(text = "One player") title.grid(column=3, row=0) global player_number player_number = 1 one_player.grid_remove() two_players.grid_remove() def twoplayers(): title.configure(text = "Two players") title.grid(column=3, row=0) global player_number player_number = 2 one_player.grid_remove() two_players.grid_remove() def add_fillers(): global filler filler = Label(window, text = " ") filler.grid(column=1, row=0) global filler2 filler2 = Label(window, text = " ") filler2.grid(column=0, row=0) global filler3 filler3 = Label(window, text = " ") filler3.grid(column=2, row=0) def choose_player_number(): one_player.grid(column= 2, row=1) two_players.grid(column= 4, row=1) def run(): add_fillers() title.grid(column=3, row=0) title.configure(text = "Rock paper scissors") choose_player_number() run() window.mainloop()
内容的提问来源于stack exchange,提问作者neo

