如何解决登录页跳转注册页的Tkinter代码错误?
Tkinter登录/注册页跳转问题修复
问题分析
原代码存在以下关键错误导致跳转失败:
- 事件绑定字符错误:使用了HTML转义的
<FocusIn>/<FocusOut>,Tkinter无法识别,需替换为原生的<FocusIn>/<FocusOut>。 - 注册页类实现错误:
RegistrationPage继承tk.Frame但未传入父窗口,且错误引用未定义的self.registrationPage,按钮还调用了不存在的self.frame属性。 - 主事件循环缺失:
LoginPage实例化后未启动mainloop,导致程序无法运行。 - 页面切换逻辑错误:直接实例化Frame作为注册页没有容器支撑,应创建独立的
Toplevel窗口承载注册界面。
修正后的完整代码
import tkinter as tk from tkinter import Tk, Frame, Label, Entry, Button, Toplevel class LoginPage: def __init__(self): self.loginPage = Tk() self.loginPage.title('Login') self.loginPage.geometry('550x510+400+100') self.loginPage.configure(bg='#075897') self.loginPage.resizable(False, False) self.frame = Frame(self.loginPage, width=350, height=350, bg='#075897') self.frame.place(x=115, y=40) self.heading = Label(self.frame, text='Unidirect', fg='black', bg='#075897', font=('Roboto', 25, 'bold')) self.heading.place(x=80, y=15) self.lblEmail = Entry(self.frame, width=25, border=0, fg='black', bg='#075897', font=('Roboto', 9)) self.lblEmail.place(x=45, y=100) self.lblEmail.insert(0, 'Email') self.lblEmail.bind('<FocusIn>', self.on_enter) self.lblEmail.bind('<FocusOut>', self.on_leave) Frame(self.frame, width=230, height=1, bg='Pink').place(x=45, y=120) self.lblPassword = Entry(self.frame, width=25, border=0, fg='black', bg='#075897', font=('Times New Roman', 9)) self.lblPassword.place(x=45, y=150) self.lblPassword.insert(0, 'Password') self.lblPassword.bind('<FocusIn>', self.on_enter) self.lblPassword.bind('<FocusOut>', self.on_leave) Frame(self.frame, width=230, height=1, bg='black').place(x=45, y=170) self.btnLogin = Button(self.frame, width=24, text='Log In', fg='black', bg='#075897', highlightbackground='blue', activeforeground='black', activebackground='#36bbf1', cursor='hand2', border=1, font=('Roboto', 11, 'bold')) self.btnLogin.place(x=25, y=210) self.txtRegister = Label(self.frame, text="Don't have an account?", fg='black', bg='#075897', font=('Arial', 9)) self.txtRegister.place(x=75, y=245) self.btnRegisterPage = Button(self.frame, width=6, text='Register', border=0, fg='black', bg='#075897', activeforeground='black', activebackground='#075897', cursor='hand2', font=('Roboto', 9, 'bold underline'), command=self.show_registration_page) self.btnRegisterPage.place(x=230, y=245) self.forgotPassword = Button(self.frame, text='Forgot Password?', bd=0, fg='black', bg='#075897', activeforeground='black', activebackground='#075897', cursor='hand2', font=('Times New Roman', 9)) self.forgotPassword.place(x=175, y=180) # 启动主事件循环 self.loginPage.mainloop() def on_enter(self, e): if e.widget == self.lblEmail: self.lblEmail.delete(0, 'end') elif e.widget == self.lblPassword: self.lblPassword.delete(0, 'end') def on_leave(self, e): if e.widget == self.lblEmail: if self.lblEmail.get() == '': self.lblEmail.insert(0, 'Email') elif e.widget == self.lblPassword: if self.lblPassword.get() == '': self.lblPassword.insert(0, 'Password') def show_registration_page(self): self.loginPage.withdraw() # 创建注册页窗口 RegistrationPage(self.loginPage) class RegistrationPage: def __init__(self, parent): self.parent = parent self.registrationPage = Toplevel(parent) self.registrationPage.title('Register') self.registrationPage.geometry('550x510+400+100') self.registrationPage.configure(bg='#075897') self.registrationPage.resizable(False, False) self.frame = Frame(self.registrationPage, width=350, height=350, bg='#075897') self.frame.place(x=115, y=40) # 注册表单元素 label_firstname = Label(self.frame, text="First Name:", bg='#075897', font=('Roboto', 9)) label_firstname.grid(row=0, column=0, padx=10, pady=5) entry_firstname = Entry(self.frame) entry_firstname.grid(row=0, column=1, padx=10, pady=5) label_lastname = Label(self.frame, text="Last Name:", bg='#075897', font=('Roboto', 9)) label_lastname.grid(row=1, column=0, padx=10, pady=5) entry_lastname = Entry(self.frame) entry_lastname.grid(row=1, column=1, padx=10, pady=5) label_email = Label(self.frame, text="Email:", bg='#075897', font=('Roboto', 9)) label_email.grid(row=2, column=0, padx=10, pady=5) entry_email = Entry(self.frame) entry_email.grid(row=2, column=1, padx=10, pady=5) label_password = Label(self.frame, text="Password:", bg='#075897', font=('Roboto', 9)) label_password.grid(row=3, column=0, padx=10, pady=5) entry_password = Entry(self.frame, show="*") entry_password.grid(row=3, column=1, padx=10, pady=5) # 注册按钮 self.btnRegister = Button(self.frame, width=24, text='Register', fg='black', bg='#075897', highlightbackground='blue', activeforeground='black', activebackground='#36bbf1', cursor='hand2', border=1, font=('Roboto', 11, 'bold'), command=self.back_to_login) self.btnRegister.grid(row=4, column=0, columnspan=2, pady=20) # 关闭注册页时恢复登录页 self.registrationPage.protocol("WM_DELETE_WINDOW", self.back_to_login) def back_to_login(self): self.registrationPage.destroy() self.parent.deiconify() # 启动登录页 LoginPage()
关键修改说明
- 修正了事件绑定的字符,将
<FocusIn>替换为<FocusIn>,确保Tkinter能识别焦点事件。 - 重构
RegistrationPage:改为创建Toplevel窗口作为注册界面载体,添加返回登录页的逻辑,关闭注册页时自动恢复登录页显示。 - 在
LoginPage的__init__末尾添加self.loginPage.mainloop(),启动主事件循环。 - 统一注册页的UI风格与登录页保持一致,修复按钮的父容器引用错误。
内容的提问来源于stack exchange,提问作者Mawahib Ali
相关产品推荐
相关产品推荐

