Tkinter接鸡蛋游戏报_tkinter.TclError: invalid command name ".!canvas"求解决
问题修复说明
报错根因
_tkinter.TclError: invalid command name ".!canvas" 报错是因为游戏结束调用root.destroy()销毁窗口后,你之前注册的create_egg、move_eggs、check_catch三个定时任务仍然会触发执行,此时Canvas组件已经被销毁,调用Canvas相关操作就会抛出异常。
除此之外你的代码还有两处逻辑错误导致游戏无法正常运行:
- 接蛋器初始坐标笔误:
catcher_start_x2 = catcher_start_x = catcher_width应为catcher_start_x2 = catcher_start_x + catcher_width,否则接蛋器初始位置错误无法接蛋 - 接蛋判定逻辑错误:
check_catch函数中的catcher_y2 - egg_y2 - egg_y2 < 40多减了一次egg_y2,应为catcher_y2 - egg_y2 < 40
完整修复代码
from itertools import cycle from random import randrange from tkinter import Canvas, Tk, messagebox, font canvas_width = 800 canvas_height = 400 root = Tk() c = Canvas(root, width = canvas_width, height = canvas_height, background="deep sky blue") c.create_rectangle(-5, canvas_height - 100, canvas_width + 5, canvas_height + 5, fill = "sea green", width=0) c.create_oval(-80, -80, 120, 120, fill="orange", width=0) c.pack() color_cycle = cycle(["light blue", "light green", "light pink", "light yellow", "light cyan"]) egg_width = 45 egg_height = 55 egg_score = 10 egg_speed = 500 egg_interval = 4000 difficulty_factor = 0.95 catcher_color = "magenta" catcher_width = 100 catcher_height = 100 catcher_start_x = canvas_width / 2 - catcher_width / 2 catcher_start_y = canvas_height - catcher_width - 20 # 修复接蛋器初始坐标笔误 catcher_start_x2 = catcher_start_x + catcher_width catcher_start_y2 = catcher_start_y + catcher_height catcher = c.create_arc(catcher_start_x, catcher_start_y, catcher_start_x2, catcher_start_y2, start = 200, extent = 140, style = "arc", outline = catcher_color, width = 3) game_font = font.nametofont("TkFixedFont") game_font.config(size = 18) score = 0 score_text = c.create_text(10, 10, anchor="nw" , font=game_font, fill="darkblue", text="Score: " + str(score)) lives_remaining = 1 lives_text = c.create_text(canvas_width - 10, 10, anchor="ne", font = game_font, fill="darkblue", text = "Lives: " + str(lives_remaining)) eggs = [] # 新增游戏运行状态标记,避免销毁窗口后定时任务继续执行 game_running = True def create_egg(): if not game_running: return x = randrange(10, 740) y = 40 new_egg = c.create_oval(x, y, x + egg_width, y + egg_height, fill = next(color_cycle), width=0) eggs.append(new_egg) root.after(egg_interval, create_egg) def move_eggs(): if not game_running: return for egg in eggs: (egg_x, egg_y, egg_x2, egg_y2) = c.coords(egg) c.move(egg, 0, 10) if egg_y2 > canvas_height: egg_dropped(egg) root.after(egg_speed, move_eggs) def egg_dropped(egg): eggs.remove(egg) lose_a_life() if lives_remaining == 0: global game_running # 游戏结束先修改状态标记,停止所有定时任务 game_running = False messagebox.showinfo("Game Over!", "Final Score: " + str(score)) root.destroy() def lose_a_life(): global lives_remaining lives_remaining -= 1 c.itemconfigure(lives_text, text = "Lives: " + str(lives_remaining)) def check_catch(): if not game_running: return (catcher_x, catcher_y, catcher_x2, catcher_y2) = c.coords(catcher) for egg in eggs: (egg_x, egg_y, egg_x2, egg_y2) = c.coords(egg) # 修复接蛋判定逻辑错误 if catcher_x < egg_x and egg_x2 < catcher_x2 and catcher_y2 - egg_y2 < 40: eggs.remove(egg) c.delete(egg) increase_score(egg_score) root.after(100, check_catch) def increase_score(points): global score, egg_speed, egg_interval score += points egg_speed = int(egg_speed * difficulty_factor) egg_interval = int(egg_interval * difficulty_factor) c.itemconfigure(score_text, text="Score: " + str(score)) def move_left(event): (x1, y1, x2, y2) = c.coords(catcher) if x1 > 0: c.move(catcher, -20, 0) def move_right(event): (x1, y1, x2, y2) = c.coords(catcher) if x2 < canvas_width: c.move(catcher, 20, 0) c.bind("<Left>" , move_left) c.bind("<Right>" , move_right) c.focus_set() root.after(1000, create_egg) root.after(1000, move_eggs) root.after(1000, check_catch) root.mainloop()
内容的提问来源于stack exchange,提问作者Hallows
相关产品推荐
相关产品推荐

