Tkinter机票预订系统:登录注册页切换后程序闪退问题
解决Tkinter登录/注册页面多次切换后程序退出的问题
问题根源
你当前用import模块+销毁主窗口的方式切换页面,存在两个致命问题:
- Python模块只会被导入一次,第二次点击
Signup按钮时,import signup不会再执行注册页的窗口创建代码,而原登录窗口已经被destroy,程序没有活跃窗口就直接退出了。 - 多次创建
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
相关产品推荐
相关产品推荐

