Tkinter游戏二次点击按钮报错_bad window path name ".!button4"的解决咨询
修复Tkinter剪刀石头布游戏二次点击按钮报错问题
你开发的剪刀石头布游戏首次运行正常,但二次点击paper/scissors/rock按钮时抛出_tkinter.TclError: bad window path name ".!button4"错误,原因是重启按钮被销毁后再次调用其place方法导致找不到窗口对象。
错误根源
- 初始化时创建了
restart_btn,第一次游戏结束后调用restart_btn.place()显示按钮正常。 - 点击restart按钮后,
restart()函数中执行restart_btn.destroy()销毁了该按钮,此时restart_btn变量指向的窗口对象已不存在。 - 第二次游戏结束时,
win_check()再次调用restart_btn.place(),尝试对已销毁的窗口执行布局操作,触发报错。
修复方案
不要销毁restart_btn,改用place_forget()方法隐藏按钮,需要显示时再调用place()。这样按钮对象始终存在,不会出现找不到窗口的问题。
修复后的完整代码
import tkinter as tk from PIL import ImageTk from random import randint root = tk.Tk() root.geometry('700x512') root.resizable(0, 0) player_selection = '' psr = ['p', 's', 'r'] ai_selection = '' game_result = '' index = 0 ai_image, player_image = '', '' imgpaper = ImageTk.PhotoImage(file='paper.png') imgscissors = ImageTk.PhotoImage(file='scissors.png') imgrock = ImageTk.PhotoImage(file='rock.png') imgempty = ImageTk.PhotoImage(file='empty.png') def ai_moves(): global ai_selection, index index = randint(0, 2) ai_selection = psr[index] image_to_output_ai() win_check() def image_to_output_ai(): global ai_image, ai_selection if ai_selection == 'p': ai_image = imgpaper elif ai_selection == 's': ai_image = imgscissors elif ai_selection == 'r': ai_image = imgrock elif ai_selection == '': ai_image = imgempty # 修复原代码变量赋值错误 def image_to_output_player(): global player_image if player_selection == 'p': player_image = imgpaper elif player_selection == 's': player_image = imgscissors elif player_selection == 'r': player_image = imgrock elif player_selection == '': player_image = imgempty def block_buttons(): btnpaper.config(state='disabled') btnscissors.config(state='disabled') btnrock.config(state='disabled') def win_check(): global game_result, ai_selection global ai_image image_to_output_player() player_label.config(image=player_image) ai_label.config(image=ai_image) if player_selection == ai_selection: game_result = 'draw' label_win_lose.config(text='平局') elif (player_selection == 'p' and ai_selection == 'r') or (player_selection == 's' and ai_selection == 'p') or (player_selection == 'r' and ai_selection == 's'): game_result = 'win' label_win_lose.config(text='你赢了!') elif (ai_selection == 'p' and player_selection == 'r') or (ai_selection == 's' and player_selection == 'p') or (ai_selection == 'r' and player_selection == 's'): game_result = 'lose' label_win_lose.config(text='你输了!') block_buttons() restart_btn.place(x=350, y=320) print(game_result) def player_selection_def(what): global player_selection player_selection = what ai_moves() def restart(): player_label.config(image=imgempty) ai_label.config(image=imgempty) btnpaper.config(state='normal') btnscissors.config(state='normal') btnrock.config(state='normal') ai_selection, player_selection = '', '' ai_image, player_image = '', '' label_win_lose.config(text='') # 改用place_forget()隐藏按钮,而非销毁对象 restart_btn.place_forget() btnpaper = tk.Button(root, text='paper', font='arial 18 bold', command=lambda: player_selection_def('p')) btnpaper.place(width=135, height=54, x=50, y=400) btnscissors = tk.Button(root, text='scissors', font='arial 18 bold', command=lambda: player_selection_def('s')) btnscissors.place(width=135, height=54, x=280, y=400) btnrock = tk.Button(root, text='rock', font='arial 18 bold', command=lambda: player_selection_def('r')) btnrock.place(width=135, height=54, x=525, y=400) player_label = tk.Label(root) player_label.place(x=50, y=50) ai_label = tk.Label(root) ai_label.place(x=400, y=50) label_win_lose = tk.Label(text='', font='arial 18 bold') label_win_lose.place(x=350, y=300) restart_btn = tk.Button(root, text='try again', font='arial 18 bold', command=restart) root.mainloop()
关键修改点
- 在
restart()函数中,将restart_btn.destroy()替换为restart_btn.place_forget(),仅隐藏按钮而非销毁对象。 - 修复
image_to_output_ai()函数中的笔误:原代码ai_selection = imgempty改为ai_image = imgempty,避免变量赋值错误。 - 添加了
label_win_lose的文本更新,让游戏结果可视化显示。
内容的提问来源于stack exchange,提问作者ProgrammistXY
相关产品推荐
相关产品推荐

