0

I am trying to create a web app with different pages. Till now I have created a log in page and home page. I have created each page as a frame. When I log in it directs me to home page. Until this the db and UI works well.

Now I would like to have different menubar for each frame.

My HomePage should have menubar with options 'Home' and 'Careers'.

To implement this I created a function for menbar in HomePage. I took the reference from Tkinter add menu bar in Frames

The code I executed is as given below

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()
        menubar = frame.menubar(self)
        self.configure(menu=menubar)

class BasePage(tk.Frame):

    def __init__(self, parent, controller):

        super().__init__(parent)
        self.controller = controller
        self.root = parent

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


class LoginPage(BasePage):

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

        login_frame = tk.Frame(self, width=200, height=50,background="white")
        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="white")
        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="white")
        self.label_username.grid(row=50, column=20, padx=10, pady=10)

        self.entry_username = tk.Entry(login_frame, width=15, font=("Helvetica", 20),bd = 3)
        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="white")
        self.label_password.grid(row=60, column=20, padx=10, pady=10)

        self.entry_password = tk.Entry(login_frame, width=15, font=("Helvetica", 20),bd = 3)
        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(),self.controller.show_frame("HomePage")], font=("Helvetica", 20),
                                      bg="white")
        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)

    def menubar(self):
        menubar = tk.Menu(self.master)
        pageMenu = tk.Menu(menubar)
        pageMenu.add_command(label="Home")
        pageMenu.add_command(label= "Careers")
        return menubar

app = App()
app.mainloop()

The error I am getting is as follows:

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 107, 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 35, in show_frame
    menubar = frame.menubar(self)
AttributeError: 'LoginPage' object has no attribute 'menubar'

Can anyone tell why does it shows attribute error? I am not able to understand the concept.

  • 1
    You can set a menu to a window, not to a frame. – acw1668 Apr 12 '21 at 15:01
  • 1
    The error means what it says. There is no `menu` option for a frame. – Delrius Euphoria Apr 12 '21 at 15:11
  • Does this answer your question? [Tkinter add menu bar in Frames](https://stackoverflow.com/questions/37621071/tkinter-add-menu-bar-in-frames) – Thingamabobs Apr 12 '21 at 15:18
  • @Atlas435 I tried your suggestion but it gives AttributeError: 'LoginPage' object has no attribute 'menubar' – Archana Jalaja Surendran Apr 14 '21 at 13:44
  • @ArchanaJalajaSurendran this line is important `menubar = tk.Menu(root)` root means the instance of `tk.Tk()` which is subclassed by your class `App` which you give as parameter `parent`. Either you do a line of `self.root = parent` in your `__init__` method of BaseFrame to have access to your instance or you go for the built_in way by `menubar = tk.Menu(self.master)` – Thingamabobs Apr 14 '21 at 14:20
  • @Atlas435 I have modified my code based on what I understood.. but I am getting the same error .. can you please explain in simple terms? – Archana Jalaja Surendran Apr 15 '21 at 13:28

0 Answers0