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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 15:45:02