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

Tkinter机票预订系统:登录注册页切换后程序闪退问题

解决Tkinter登录/注册页面多次切换后程序退出的问题

问题根源

你当前用import模块+销毁主窗口的方式切换页面,存在两个致命问题:

  1. Python模块只会被导入一次,第二次点击Signup按钮时,import signup不会再执行注册页的窗口创建代码,而原登录窗口已经被destroy,程序没有活跃窗口就直接退出了。
  2. 多次创建Tk()实例(登录页win=Tk(),注册页win2=Tk())违反Tkinter规则,Tkinter仅允许一个主窗口实例,多实例会导致不可预期的行为。

修复方案(最小改动版本)

我们改用Toplevel创建子窗口,配合窗口隐藏/显示来实现切换,避免销毁主窗口和重复导入问题。

1. 修改登录页代码

将signup函数改为隐藏登录窗口,导入注册模块:

def signup():
    win.withdraw()  # 隐藏登录窗口,而非销毁
    import signup

2. 修改注册页代码

  • 将主窗口从Tk()改为Toplevel,作为登录窗口的子窗口
  • 修改返回登录的函数,销毁注册窗口并重新显示登录窗口
  • 修复变量名重复覆盖的问题(比如fname同时用作Label、StringVar、Entry的变量名,导致引用混乱)

修改后的注册页核心代码:

from tkinter import *
from tkinter import messagebox
from tkinter import ttk
import mysql.connector
import login  # 提前导入登录模块,方便操作登录窗口

# 将Tk()改为Toplevel,作为登录窗口的子窗口
win2 = Toplevel(login.win)
win2.title("AirWaves")
win2.geometry('1366x768+100+50')
win2.configure(bg="#fff")
win2.resizable(False, False)

def clear():
    fname_entry.delete(0, END)
    lname_entry.delete(0, END)
    dob_entry.delete(0, END)
    pportno_entry.delete(0, END)
    phone_entry.delete(0, END)
    email_entry.delete(0, END)
    username_entry.delete(0, END)
    password_entry.delete(0, END)
    veripass_entry.delete(0, END)

def back_to_login():
    win2.destroy()  # 销毁注册窗口
    login.win.deiconify()  # 重新显示登录窗口

# 修复变量名覆盖问题,Label、StringVar、Entry使用不同变量名
# Label部分
fname_label = Label(win2, text ="First Name", font ='Perpetua 25 bold', bg="#fff")
fname_label.place(x=50 , y=140)

lname_label = Label(win2, text ="Last Name", font ='Perpetua 25 bold', bg="#fff")
lname_label.place(x=50 , y=220)

gender_label = Label(win2, text ="Gender", font ='Perpetua 25 bold', bg="#fff")
gender_label.place(x=50 , y=300)

# StringVar部分
fname_var = StringVar()
lname_var = StringVar()
gender_var = StringVar()
dob_var = StringVar()
pportno_var = StringVar()
phone_var = StringVar()
email_var = StringVar()
username_var = StringVar()
password_var = StringVar()
veripass_var = StringVar()

# Entry部分
fname_entry = Entry(win2, font ='Perpetua 20 bold', bg="#fff", textvariable=fname_var)
fname_entry.place(x=250, y=140)

lname_entry = Entry(win2, font ='Perpetua 20 bold', bg="#fff", textvariable=lname_var)
lname_entry.place(x=250, y=220)

# 性别单选按钮部分
s=ttk.Style()
s.configure('bg.TRadiobutton', background="#fff", font ='Perpetua 20 bold')
genderm = ttk.Radiobutton(win2, text='Male', value="Male", variable=gender_var, style='bg.TRadiobutton')
genderm.place(x= 250 , y= 280)
genderf = ttk.Radiobutton(win2, text='Female', value="Female", variable=gender_var, style='bg.TRadiobutton')
genderf.place(x= 250 , y= 330)

# 其余Entry、Label同理修改变量名,确保不重复覆盖
dob_label = Label(win2, text ="D.O.B", font ='Perpetua 25 bold', bg="#fff")
dob_label.place(x=50 , y=380)
dob_entry = Entry(win2, font ='Perpetua 20 bold', bg="#fff", textvariable=dob_var)
dob_entry.place(x=250, y=380)

# 修改返回按钮的command为back_to_login
b3 = Button(win2, text="Back to Login", width=13, font='Carrier 15', command=back_to_login)
b3.place(x=790,y=525)

win2.mainloop()

更优雅的方案:使用Frame切换

如果想进一步优化,建议将登录页和注册页做成Frame组件,在同一个主窗口中切换显示/隐藏Frame,这种方式更符合Tkinter的设计思路,避免多窗口管理的问题。示例思路:

import tkinter as tk

class App(tk.Tk):
    def __init__(self):
        super().__init__()
        self.title("AirWaves")
        self.geometry('1366x768+100+50')
        self.configure(bg="#fff")
        self.resizable(False, False)
        
        # 创建两个Frame
        self.login_frame = LoginFrame(self)
        self.signup_frame = SignupFrame(self)
        
        # 默认显示登录页
        self.login_frame.pack(fill="both", expand=True)
    
    def show_login(self):
        self.signup_frame.pack_forget()
        self.login_frame.pack(fill="both", expand=True)
    
    def show_signup(self):
        self.login_frame.pack_forget()
        self.signup_frame.pack(fill="both", expand=True)

class LoginFrame(tk.Frame):
    def __init__(self, parent):
        super().__init__(parent, bg="#fff")
        # 登录页的UI元素和逻辑
        # 切换到注册页的按钮command=parent.show_signup

class SignupFrame(tk.Frame):
    def __init__(self, parent):
        super().__init__(parent, bg="#fff")
        # 注册页的UI元素和逻辑
        # 返回登录页的按钮command=parent.show_login

if __name__ == "__main__":
    app = App()
    app.mainloop()

额外注意事项

  • 注册页中密码验证逻辑if (vp in passwrd)有问题,应该改为vp == passwrd,否则只要验证密码包含在原密码里就通过,比如原密码是123456,验证密码是123也会通过,不符合需求。
  • 数据库操作要添加异常捕获,比如连接失败、插入失败的情况,避免程序崩溃。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 07:59:52