Tkinter接鸡蛋游戏报错invalid command name ".!canvas"如何修复
错误原因
这个报错是Tkinter开发中典型的时序问题:
- 游戏结束时你调用了
root.destroy()直接销毁了整个窗口对象,所有依附于窗口的Canvas组件也会被同步释放 - 但此前你通过
root.after()注册的三个定时任务create_egg、move_eggs、check_catch还有未执行的回调排队等待触发 - 定时时间到后回调函数执行,调用
c.coords()操作已经被销毁的Canvas对象,就会抛出找不到组件的错误
修复方案
只要增加一个游戏运行状态标记,在销毁窗口前终止所有定时任务的执行即可,修改步骤如下:
- 初始化全局状态标记,在生命值变量定义后增加一行:
lives_remaining = 3 # 新增游戏运行状态标记 game_running = True lives_text = c.create_text(canvas_width - 10, 10, anchor="ne", font = game_font, fill="darkblue", text = "Lives " + str(lives_remaining))
- 给三个定时回调函数的开头增加状态判断,不满足条件直接终止执行,不再注册新的定时任务:
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 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 - 10 < egg_x and egg_x2 < catcher_x2 + 10 and (catcher_y2 - egg_y2) < 5: eggs.remove(egg) c.delete(egg) increase_score(egg_score) root.after(100, check_catch)
- 修改游戏结束的逻辑,销毁窗口前先把状态标记设为False,终止后续所有定时回调的执行:
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()
内容的提问来源于stack exchange,提问作者Hallows
相关产品推荐
相关产品推荐

