Ernie Peters
Ernie Peters

Reputation: 697

specific menu options in tkinter using classes

I have searched far and wide for this but could not quite get a full answer based on what I found. I'm writing a GUI in Python3 using tkinter. Everything is going to be in classes including a 'Menu' class. Couple issues - I want to use a for loop to populate my menu items and sub items (not implemented yet). - I want to do this for each frame that the 'container' class displays but I want certain items in the menus to be disabled (greyed out) when those options do not apply. i.e. Start of the program with nothing loaded the 'Save' button would not make sense so I would disable it until a 'New' project is made or an existing one opened.

My code so far.

import tkinter as tk
from tkinter import ttk, Menu


class MainFrame(tk.Tk):

    def __init__(self, *args, **kwargs):

        tk.Tk.__init__(self, *args, **kwargs)
        container = tk.Frame(self)


        #display manubar
        menubar = MenuBar(self)
        self.config(menu=menubar)

        self.frames = {}

        for F in (StartPage, PageOne, PageTwo):
            frame = F(container, self)
            self.frames[F] = frame
            frame.grid(row=0, column=0, sticky="nsew")

        self.show_frame(StartPage)

    def show_frame(self, cont):

        frame = self.frames[cont]
        frame.tkraise()


class StartPage(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)

class PageOne(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        label = ttk.Label(self, text="Page One", font=LARGE_FONT)
        label.pack(pady=10, padx=10)

        button = ttk.Button(self, text="Visit Page 2",
                            command=lambda: controller.show_frame(PageTwo))
        button1 = ttk.Button(self, text="Go to Start Page",
                             command=lambda: controller.show_frame(StartPage))

        button.pack()
        button1.pack()


class PageTwo(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        label = ttk.Label(self, text="Page Two", font=LARGE_FONT)
        label.pack(pady=10, padx=10)

        button = ttk.Button(self, text="Visit Page 1",
                            command=lambda: controller.show_frame(PageOne))
        button1 = ttk.Button(self, text="Go to Start Page",
                             command=lambda: controller.show_frame(StartPage))

        button.pack()
        button1.pack()


class MenuBar(tk.Menu):
    def __init__(self, parent):
        tk.Menu.__init__(self, parent)

        fileMenu = tk.Menu(self, tearoff=False)
        self.add_cascade(label="File",underline=0, menu=fileMenu)
        fileMenu.add_command(label="Page One", underline=0,
                             command=self.onexit)
        fileMenu.add_command(label="Page Two", underline=1,
                             command=lambda:self.onexit)
        fileMenu.add_command(label="Exit", underline=1, command=self.onexit)


    def onexit(self):
        quit()

if __name__ == "__main__":
    app = MainFrame()
    app.mainloop()

How do you call the 'PageOne' or 'Pagetwo' using the options in the file menu? For testing purposes, I am just exiting the program for now so I can run the program without errors.

Upvotes: 0

Views: 2058

Answers (1)

Bryan Oakley
Bryan Oakley

Reputation: 385900

...I am not sure how to call the 'PageOne' or 'Pagetwo' using the options in the file menu...

Just like with your pages, the MenuBar object needs to be given a reference to the controller so that it can call the controller function show_frame. Since MainFrame is both the "parent" and the "controller", you can use the one argument for both purposes.

class MenuBar(tk.Menu):
    def __init__(self, parent):
        self.controller = parent
        ...
        fileMenu.add_command(..., command=lambda: self.controller.show_frame(PageOne))
        fileMenu.add_command(..., command=lambda: self.controller.show_frame(PageTwo))
        ...

Upvotes: 1

Related Questions