You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 08:35:11