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

如何通过一个按钮关闭多个Tkinter窗口并继续执行程序

解决Tkinter登录后无法关闭两个窗口的问题

看起来你遇到的核心问题有两个:一是调用destroy时漏掉了括号,二是在登录成功时重新使用了rootA变量名,覆盖了原来的登录窗口引用,导致无法正确关闭初始的登录界面。下面是具体的解决思路和修改后的代码:

问题分析

  • 在CheckLogin函数中,登录成功时你创建了一个新的rootA = Tk(),这会覆盖全局变量rootA原本指向的登录窗口对象,所以后续在LoginSuccessful里调用rootA.destroy()(哦对,你还漏了括号)只能关闭这个新的提示窗口,而关不了原来的登录窗口。
  • Tkinter应用建议只保留一个主Tk()实例,其他弹窗应该用Toplevel()来创建,这样窗口管理会更清晰。

解决方案步骤

  1. 修复destroy()的调用:确保调用方法时加上括号,否则只是引用方法而不会执行。
  2. 区分窗口变量名:给登录成功的提示窗口起一个独立的名字(比如success_win),不要覆盖登录窗口的rootA变量。
  3. 全局化提示窗口引用:让LoginSuccessful能同时访问登录窗口和提示窗口的引用,从而关闭两者。
  4. 改用Toplevel创建弹窗:替代新的Tk()实例,符合Tkinter的最佳实践。

修改后的完整代码

import time
import openpyxl
from openpyxl import load_workbook
import tkinter as tk
from tkinter import *
import sys

user1 = 'testing'  # 直接全局定义,避免Function()的冗余
password1 = '0000'

def Login_form():
    global username, password, rootA
    rootA = Tk()
    rootA.title('User Authentication')
    msgbox1 = Label(rootA, text='Please Login\n')
    msgbox1.grid(sticky=E)
    
    username_label = Label(rootA, text='Username: ')
    password_label = Label(rootA, text='Password: ')
    username_label.grid(row=1, sticky=W)
    password_label.grid(row=2, sticky=W)
    
    username = Entry(rootA)
    password = Entry(rootA, show='*')
    username.grid(row=1, column=1)
    password.grid(row=2, column=1)
    
    login_btn = Button(rootA, text='Login', command=CheckLogin)
    exit_btn = Button(rootA, text='Exit', command=sys.exit)
    login_btn.grid(row=4, column=1)
    exit_btn.grid(row=4, column=2)
    
    rootA.mainloop()

def CheckLogin():
    global success_win  # 全局化成功窗口引用
    if username.get() == user1 and password.get() == password1:
        # 用Toplevel创建弹窗,而不是新的Tk()
        success_win = Toplevel(rootA)
        success_win.title('Authentication Check')
        success_win.geometry('150x100')
        rlbl = Label(success_win, text='\n Logged In')
        rlbl.pack()
        okay_btn = Button(success_win, text='Okay', command=LoginSuccessful)
        okay_btn.pack()
    else:
        error_win = Toplevel(rootA)
        error_win.title('Authentication Check')
        error_win.geometry('150x160')
        rlbl = Label(error_win, text='\n Invalid Login')
        rlbl.pack()
        okay_btn = Button(error_win, text='Try Again', command=error_win.destroy)
        okay_btn.pack()
        exit_btn = Button(error_win, text='Exit', command=sys.exit)
        exit_btn.pack()

def LoginSuccessful():
    # 关闭登录窗口和成功提示窗口
    rootA.destroy()
    success_win.destroy()
    print("ANCD")
    # 这里可以继续执行你的后续任务,比如调用Insert_Rows()
    # Insert_Rows()

def Insert_Rows():
    # 你的原有逻辑,这里假设All_Users_Sheet已经定义
    for rows in range(len(All_Users_Sheet)):
        if rows == 0:
            continue
        if All_Users_Sheet[rows][10].value is None:
            break
        else:
            print(All_Users_Sheet[rows][10].value)
            print(type(All_Users_Sheet[rows][10].value))

Login_form()

额外优化点

  • 把user1和password1直接全局定义,去掉了冗余的Function()。
  • 给登录窗口的标签重命名(username_label),避免和输入框的username变量重名,防止潜在的变量覆盖问题。
  • 所有弹窗都改用Toplevel,基于主窗口rootA创建,这样窗口层级更清晰,关闭主窗口时也会自动关闭所有子窗口(不过这里我们手动关闭了)。

这样修改后,点击Okay按钮就能同时关闭登录窗口和成功提示窗口,程序也会继续执行后续任务啦。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 08:07:17