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

如何解决登录页跳转注册页的Tkinter代码错误?

Tkinter登录/注册页跳转问题修复

问题分析

原代码存在以下关键错误导致跳转失败:

  1. 事件绑定字符错误:使用了HTML转义的&lt;FocusIn&gt;/&lt;FocusOut&gt;,Tkinter无法识别,需替换为原生的<FocusIn>/<FocusOut>。
  2. 注册页类实现错误:RegistrationPage继承tk.Frame但未传入父窗口,且错误引用未定义的self.registrationPage,按钮还调用了不存在的self.frame属性。
  3. 主事件循环缺失:LoginPage实例化后未启动mainloop,导致程序无法运行。
  4. 页面切换逻辑错误:直接实例化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()

关键修改说明

  • 修正了事件绑定的字符,将&lt;FocusIn&gt;替换为<FocusIn>,确保Tkinter能识别焦点事件。
  • 重构RegistrationPage:改为创建Toplevel窗口作为注册界面载体,添加返回登录页的逻辑,关闭注册页时自动恢复登录页显示。
  • 在LoginPage的__init__末尾添加self.loginPage.mainloop(),启动主事件循环。
  • 统一注册页的UI风格与登录页保持一致,修复按钮的父容器引用错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 00:24:55