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

Python 3中点击窗口X按钮返回上一窗口的实现问题

搞定你的Tkinter登录系统窗口关闭问题~

作为Python新手用Tkinter做登录系统时,碰到点击窗口X按钮要返回上一窗口的需求,还遇到了NameError: name 'on_close' is not defined的错误,我来帮你拆解问题并给出修正方案:

为啥会报错?

  1. 函数定义时机不对:你原来把on_close函数写在了main_Screen()调用之后,而且在login()里还写了on_close():这种语法错误的代码,导致程序需要调用这个函数的时候,它要么还没定义,要么根本不被识别。
  2. 协议绑定位置错了:screen2.protocol(...)放在全局作用域时,screen2窗口还没被创建(它是在login()里生成的),不仅会报错,也没法绑定到正确的窗口上。

修正后的完整代码

from tkinter import*
from tkinter import messagebox

w = 300
h = 2

def register_user():
    global username_info
    global password_info
    username_info = username.get()
    password_info = password.get()
    file = open(username_info+".txt", "w")
    file.write(username_info)
    file.write(password_info)
    file.close()
    username_entry.delete(0, END)
    password_entry.delete(0, END)
    # 给标签指定父组件,不然不会显示在注册窗口上
    Label(screen1, text = "Registration Success").pack()  

def register():
    global screen1
    screen.withdraw()
    screen1 = Toplevel(screen)
    screen1.title("Registration")
    screen1.geometry("300x250")
    global username
    global password
    global username_entry
    global password_entry
    username = StringVar()
    password = StringVar()
    Label(screen1, text = " Please Enter Your Details Below*").pack()
    Label(screen1, text = "").pack()
    Label(screen1, text = "Username *").pack()
    username_entry = Entry(screen1, textvariable = username)
    username_entry.pack()
    Label(screen1, text = "Password *").pack()
    # 密码框添加show="*",隐藏输入内容更符合登录系统逻辑
    password_entry = Entry(screen1, textvariable = password, show="*")  
    password_entry.pack()
    Label(screen1, text = "").pack()
    Button(screen1, text= "Register", height="1", width="10", command = register_user).pack()

def login():
    global screen2
    screen.withdraw()
    screen2 = Toplevel(screen)
    screen2.title("HOT or SUPER HOT")
    screen2.geometry("500x400")
    
    # 把on_close函数定义在login内部,确保绑定协议时它已经存在
    def on_close():
        screen2.withdraw()
        # deiconify是方法,必须加括号调用!
        screen.deiconify()  
    
    # 窗口创建后立即绑定关闭事件,这才是正确的位置
    screen2.protocol("WM_DELETE_WINDOW", on_close)

def main_Screen():
    global screen
    screen = Tk()
    screen.geometry("600x300")
    screen.title("Login System")
    Label(text = "Login System" , bg = "black", width = w , height = h, font = ("Calibri", 20) , fg = "white").pack()
    Label(text = "").pack()
    Button(text = "Login", height = h, width = "30", command = login).place(x=50 , y=200)
    Label(text = "").pack()
    Button(text = "Register" ,height = h, width = "30", command = register).place(x=320 , y=200)
    screen.mainloop()

main_Screen()
print("Hello World")

核心修正要点

  • 调整函数位置:把on_close放在login()函数内部,或者提前在全局定义,保证绑定协议时函数已经存在。
  • 正确绑定关闭协议:把screen2.protocol(...)移到login()里,等screen2窗口创建完成后再绑定,避免“窗口未定义”的错误。
  • 修复语法小问题:删掉login()里无效的on_close():代码,screen.deiconify要加括号(它是Tkinter窗口的方法,必须调用)。
  • 额外优化:给密码输入框加了show="*",注册成功的标签指定了父组件,让界面逻辑更合理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 08:48:04