Reputation: 697
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
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