Tkinter grid布局Button点击关闭窗口报错 无法触发游戏状态控制逻辑
问题根因
- 类方法缩进错误:除
__init__外的所有方法都定义在Ranking类外部,属于全局函数,无法正常访问实例属性。 - 无点击状态存储逻辑:按钮触发逻辑仅关闭窗口,没有存储用户点击的按钮类型,上层代码无法获取操作结果。
- 上层调用逻辑错误:直接调用
end_game()/new_game()方法,这两个方法的作用是在窗口上创建按钮,若窗口已销毁,再次调用时创建按钮的操作就会抛出application has been destroyed报错。 - tkinter主循环阻塞特性:
generar_ranking中的mainloop()是阻塞调用,只有窗口关闭后才会继续执行后续代码,需要等待窗口关闭后再读取操作结果。
修正后的Ranking类代码
import tkinter as tk class Ranking: def __init__(self) -> None: self.partidas = [] # 新增:存储用户点击的按钮类型 self.click_action = None def agregar_partida_terminada(self, partida): self.partidas.append(partida) self.calcular_promedio() def calcular_promedio(self): for partida in self.partidas: for jugador in list(partida.keys()): lista_cantidad_de_intentos = [partida[jugador]['intentos'] for partida in self.partidas] partida[jugador]['promedio'] = sum(lista_cantidad_de_intentos) / len(lista_cantidad_de_intentos) def generar_ranking(self): self.raiz = tk.Tk() self.raiz.title("Ranking") valores_tabla = [['J', 'C', 'T', 'P']] ultima_partida = self.partidas[-1] for jugador in ultima_partida: valores_fila = [jugador] for campo in list(ultima_partida[jugador].keys()): valores_fila.append(ultima_partida[jugador][campo]) valores_tabla.append(valores_fila) for indexFila in range(len(valores_tabla)): fila = valores_tabla[indexFila] for indexCol in range(len(fila)): tk.Label(self.raiz, text=fila[indexCol]).grid(row=indexFila, column=indexCol, sticky=tk.NSEW) # 直接调用实例方法创建按钮 self.end_game() self.new_game() # 阻塞直到窗口关闭 self.raiz.mainloop() # 返回用户点击的操作类型 return self.click_action def close_ranking(self): self.raiz.destroy() # 新增:统一处理按钮点击事件 def on_button_click(self, action_type): self.click_action = action_type self.close_ranking() def end_game(self): End_Game = tk.Button(self.raiz, text="Terminar partida", command=lambda: self.on_button_click('end')) End_Game.grid(row=4, column=0) def new_game(self): New_Game = tk.Button(self.raiz, text="Jugar nueva partida", command=lambda: self.on_button_click('new')) New_Game.grid(row=4, column=3)
上层业务代码调用示例
from ranking import Ranking # 省略游戏逻辑,对局结束后初始化Ranking实例 ranking = Ranking() # 假设partida是当前结束的对局数据 ranking.agregar_partida_terminada(partida) # 调用generar_ranking会阻塞到窗口关闭,返回用户点击的操作类型 action = ranking.generar_ranking() if action == 'end': finalizar_juego = True elif action == 'new': finalizar_partida = False
核心修改说明
- 修正了类方法缩进问题,所有方法都归属到Ranking类下
- 新增
click_action属性存储用户操作类型,窗口关闭后上层可以直接读取 - 不再需要上层调用
end_game()/new_game()方法,避免了窗口销毁后重复创建按钮的报错 generar_ranking直接返回操作结果,上层逻辑更简洁清晰
内容的提问来源于stack exchange,提问作者Jota
相关产品推荐
相关产品推荐

