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

如何通过tkinter按钮触发的内层函数终止外层主函数并处理GUI关闭报错

解决方案

1. 核心问题对应解法

你遇到的两个核心问题无需用类或抛异常就能解决:

  • 内层按钮触发函数无法终止外层函数:tkinter自带root.quit()方法可以直接退出root.mainloop()循环,直接执行外层函数后续逻辑,配合全局标记位即可完全符合你的需求
  • 调用root.destroy()触发iconphoto报错:root.destroy()会直接销毁root对象,后续代码访问root属性就会触发报错,替换为root.withdraw()隐藏窗口即可,全程只保留一个Tk实例无需重复创建

2. 具体修改点

  • 给窗口绑定WM_DELETE_WINDOW关闭事件,触发时直接弹出确认框
  • 输入合规后调用root.quit()退出主循环,不需要销毁窗口
  • 移除重复创建Tk实例的逻辑,全程只初始化一次root,避免重复调用iconphoto报错

3. 修改后完整可运行代码

import tkinter as tk
from tkinter import messagebox as msgbox
from PIL import ImageTk
lst = []
# 全局标记位:标记用户是否选择直接退出程序
exit_flag = False

black = '#%02x%02x%02x' % (50, 50, 50)
white = '#%02x%02x%02x' % (240, 240, 240)
red = '#%02x%02x%02x' % (255, 80, 80)
yellow = '#%02x%02x%02x' % (255, 220, 80)
green = '#%02x%02x%02x' % (120, 255, 150)
blue = '#%02x%02x%02x' % (0, 220, 240)
purple = '#%02x%02x%02x' % (120, 80, 255)

window_icon = 'icon.jpg'

# 全程只初始化一次root,避免重复创建报错
root = tk.Tk()
root.withdraw()
root.iconphoto(True, ImageTk.PhotoImage(file=window_icon))
root.attributes("-topmost", True)

def root_win():
    global lst, exit_flag
    lst = []
    exit_flag = False
    root.deiconify()

    w_root = 500
    h_root = 320

    pos_right = round(root.winfo_screenwidth() / 2 - w_root / 2)
    pos_down = round(root.winfo_screenheight() / 2 - h_root / 2)

    root.title('Enter the values')
    root.resizable(width=False, height=False)
    root.geometry('{}x{}+{}+{}'.format(w_root, h_root, pos_right, pos_down))
    root.configure(bg=white)

    # 清空窗口旧组件,避免重复创建
    for widget in root.winfo_children():
        widget.destroy()

    tk.Label(root, text='Enter the values', font=('bold', 30), bg=white, fg=black).place(x=70, y=20)
    tk.Label(root, text='Enter width here:', font=('bold', 15), bg=white, fg=black).place(x=50, y=100)
    tk.Label(root, text='Enter height here:', font=('bold', 15), bg=white, fg=black).place(x=50, y=140)

    val1 = tk.Entry(root, bd=0, font=('bold', 15))
    val1.place(x=280, y=102, width=170)

    val2 = tk.Entry(root, bd=0, font=('bold', 15))
    val2.place(x=280, y=142, width=170)

    lbl = tk.Label(root, text='Min: 5, Max: 100', font=('bold', 15), bg=white, fg=purple)
    lbl.place(x=170, y=260)

    def enter():
        global lst
        if val1.get() == '' and val2.get() == '':
            lbl.config(text='Please enter width and height!')
            lbl.place(x=80, y=260)

        elif val1.get() == '':
            lbl.config(text='Please enter a width!')
            lbl.place(x=145, y=260)

        elif val2.get() == '':
            lbl.config(text='Please enter a height!')
            lbl.place(x=140, y=260)

        else:
            wid, hit = 0, 0
            try:
                wid = round(float(val1.get()))
                hit = round(float(val2.get()))
            except:
                lbl.config(text='Please enter value from 5 to 100!')
                lbl.place(x=70, y=260)
                return

            if not 5 <= wid <= 100 or not 5 <= hit <= 100:
                lbl.config(text='Please enter value from 5 to 100!')
                lbl.place(x=70, y=260)
                return

            lbl.config(text='INPUT ACCEPTED !!!!')
            lbl.place(x=130, y=260)
            lst = [wid, hit]
            # 输入合规,隐藏窗口退出主循环
            root.withdraw()
            root.quit()

    def clr():
        val1.delete(0, 'end')
        val2.delete(0, 'end')
        lbl.config(text='Min: 5, Max: 100')
        lbl.place(x=170, y=260)

    def on_close():
        global exit_flag
        action = msgbox.askyesno(title='Exit prompt', message='Are you sure you want to exit?\nYes: Exit\nNo: Restart\n',
                             icon='warning', default='no')
        if action:
            exit_flag = True
            root.withdraw()
            root.quit()
        else:
            # 选择重启,清空当前输入
            clr()

    # 绑定窗口关闭事件
    root.protocol("WM_DELETE_WINDOW", on_close)

    enter = tk.Button(root, text='Enter', font=('bold', 15), bd=0, fg=black, bg=green, activebackground=blue,
                      command=enter)
    enter.place(x=300, y=200)
    enter.configure(width=8)

    clear = tk.Button(root, text='Clear', font=('bold', 15), bd=0, fg=black, bg=red, activebackground=yellow,
                      command=clr)
    clear.place(x=100, y=200)
    clear.configure(width=8)

    root.mainloop()

while True:
    root_win()
    # 用户选择直接退出则终止程序
    if exit_flag:
        break
    # 拿到合规输入则终止循环
    if lst:
        break

print(lst)

内容的提问来源于stack exchange,提问作者Ishan Jindal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 16:36:03