无法在 tkinter 框架之间导航。它显示属性错误

Cannot navigate between tkinter frames. It shows Attribute error

我浏览了几篇关于 tkinter 框架之间导航的文章,但没有发现它们有用。我正在尝试创建一个应用程序。我有一个登录页面和主页。我想在登录页面中提交按钮的单击事件中的这两个框架之间导航。单击提交按钮时,我使用了两个函数。我也做了数据库连接。

当程序执行时,它显示登录 Page.After 输入详细信息,当我单击提交按钮时它显示属性错误。

以下是我执行的代码。

import tkinter as tk
from tkinter import ttk
import mysql.connector
from tkinter import messagebox


class App(tk.Tk):
    bg_img_path = "images\bg9.png"

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.geometry("1500x750")

        main_frame = tk.Frame(self, width=200, height=50, highlightbackground="black", highlightthickness=1,
                              background="#e6ffe6")
        main_frame.pack(side='top', fill='both', expand='True')

        main_frame.grid_rowconfigure(0, weight=1)
        main_frame.grid_columnconfigure(0, weight=1)

        self.bkgr_image = tk.PhotoImage(file=self.bg_img_path)

        self.frames = {}
        for F in (LoginPage,HomePage):
            page_name = F.__name__
            frame = F(main_frame, self)
            self.frames[page_name] = frame
            frame.grid(row=0, column=0, sticky='nsew')

        self.show_frame(LoginPage)

    def show_frame(self, container):
        frame = self.frames[container]
        frame.tkraise()


class BasePage(tk.Frame):

    def __init__(self, parent, controller):
        super().__init__(parent)

        label_bkgr = tk.Label(self, image=controller.bkgr_image)
        label_bkgr.place(x=0, y=0)


class LoginPage(BasePage,tk.Frame):

    def __init__(self, parent, controller):
        super().__init__(parent, controller)

        login_frame = tk.Frame(self, width=200, height=50, highlightbackground="black", highlightthickness=1,
                               background="#e6ffe6")
        login_frame.grid(row=400, column=20, padx=500, pady=250)

        self.label_title = tk.Label(login_frame, text="Log In", font=("Helvetica", 40), bg="#e6ffe6")
        self.label_title.grid(row=0, column=20, padx=10, pady=10)

        self.label_username = tk.Label(login_frame, text="Username", font=("Helvetica", 20), bg="#e6ffe6")
        self.label_username.grid(row=50, column=20, padx=10, pady=10)

        self.entry_username = tk.Entry(login_frame, width=15, font=("Helvetica", 20))
        self.entry_username.grid(row=50, column=30, padx=10, pady=10)

        self.label_password = tk.Label(login_frame, text="Password", font=("Helvetica", 20), bg="#e6ffe6")
        self.label_password.grid(row=60, column=20, padx=10, pady=10)

        self.entry_password = tk.Entry(login_frame, width=15, font=("Helvetica", 20))
        self.entry_password.grid(row=60, column=30, padx=10, pady=10)

        self.login_button = tk.Button(login_frame, text="Log In", command=lambda: [self.submit,App.show_frame(self,HomePage)], font=("Helvetica", 20),
                                      bg="#e6ffe6")
        self.login_button.grid(row=70, column=25, padx=10, pady=10)

    def submit(self):
        self.u_name = self.entry_username.get()
        self.p_word = self.entry_password.get()

        employee = mysql.connector.connect(host="localhost", user="root", password="", database="edatabase")
        cursor_variable = employee.cursor()

        cursor_variable.execute("INSERT INTO login VALUES ('" + self.u_name + "','" + self.p_word + "')")
        employee.commit()

        employee.close()

        messagebox.showinfo("Log In", "Succesfull")


class HomePage(BasePage):

    def __init__(self, parent, controller):
        super().__init__(parent, controller)

        label1 = ttk.Label(self, text='Home', font=("Helvetica", 20))
        label1.pack(padx=10, pady=10)

app = App()
app.mainloop()

抛出的属性错误如下:

C:\Users\write\AppData\Local\Programs\Python\Python39\python.exe "C:/Users/write/PycharmProjects/OOP trials/login_bg_img_trial2.py"
Traceback (most recent call last):
  File "C:\Users\write\PycharmProjects\OOP trials\login_bg_img_trial2.py", line 97, in <module>
    app = App()
  File "C:\Users\write\PycharmProjects\OOP trials\login_bg_img_trial2.py", line 30, in __init__
    self.show_frame(LoginPage)
  File "C:\Users\write\PycharmProjects\OOP trials\login_bg_img_trial2.py", line 33, in show_frame
    frame = self.frames[container]
KeyError: <class '__main__.LoginPage'>

Process finished with exit code 1

感谢任何帮助。

在您的 App.__init__ 更改中:

self.show_frame(LoginPage)

self.show_frame("LoginPage")

您拥有的字典 (self.frames) 包含作为键的框架名称和作为值的框架实例。


同时将 self.controller = controller 添加到 BasePage.__init__ 以便您可以保留对 controller.

的引用

这将允许您更改

self.login_button = tk.Button(..., command=lambda: [..., App.show_frame(self,HomePage)])

进入:

self.login_button = tk.Button(..., command=lambda: [..., self.controller.show_frame("HomePage")])

这应该可以解决所有问题


请注意,正如@Atlas435 所说,您不需要 class LoginPage(BasePage,tk.Frame) 中的 tk.Frame。在 lambda 中使用列表来执行函数也是非 pythonic 的。只定义一个新函数更容易。