I am creating a gui with python 3.7 using tinter. Everything works fine in Windows. But when I run the program on Mac, the menu bar does not change while switching frames. In my real world application (which is more complex), interacting with the menu bar, after changing frames, causes the program to crash.
The same script (below) has three classes, one to build the frame with scrollbars and the other two to switch between frames - each frame has its own menubar.
Running the program in python 3.11 yields the same problem.
""" program to test tkinter menu on mac """
from tkinter import Frame, Scrollbar, Canvas, BOTH, LEFT, BOTTOM, NW, RIGHT, mainloop, Tk, Label, Button, Menu
class MakeWindow:
"""
creates a window with a scrollbar and a frame for buttons on the bottom
use win (or self.win) = MakeWindow() to call the object
use win.create(frame) to build screen
call win.finish() at the end of the widgets
"""
def __init__(self):
self.topframe = Frame(root)
self.s = Scrollbar(self.topframe)
self.c = Canvas(self.topframe, width=1600)
self.body = Frame(self.c)
self.buttons = Canvas(self.topframe) # button bar
self.move_mousewheel = True
def create(self, frame):
""" call this method to build the window. If a frame is passed, it will be destroyed """
if frame is not None:
frame.destroy() # close out the previous frame
self.topframe.pack(fill=BOTH, side=LEFT) # pack topframe on the root
self.buttons.pack(fill=BOTH, side=BOTTOM) # pack buttons on the topframe
self.s.pack(side=RIGHT, fill=BOTH) # pack scrollbar on topframe
self.c.pack(side=LEFT, fill=BOTH) # pack canvas on topframe
self.s.configure(command=self.c.yview, orient="vertical")
# link up the canvas and scrollbar
self.c.configure(yscrollcommand=self.s.set)
# link up the canvas and the scrollbar
self.c.create_window((0, 0), window=self.body, anchor=NW)
def finish(self):
""" This closes the window created by create() """
root.update()
self.c.config(scrollregion=self.c.bbox("all"))
try:
mainloop()
except KeyboardInterrupt:
root.destroy()
class Screens:
""" make windows and pulldown menu """
def __init__(self):
self.win = None
def pulldown_menu(self):
""" create a pulldown menu, and add it to the menu bar """
menubar = Menu(self.win.topframe)
basic_menu = Menu(menubar, tearoff=0)
menubar.add_cascade(label="First File", menu=basic_menu)
basic_menu.add_command(label="print hello there", command=lambda: print("hello there"))
root.config(menu=menubar)
def make_mainframe(self, frame=None):
""" master method for controlling methods in class """
self.win = MakeWindow()
self.win.create(frame) # create the window
self.pulldown_menu()
mainframe = Frame(self.win.body)
mainframe.pack()
Label(mainframe, text="Main Frame: menu bar should have 'First File' option").pack()
Button(mainframe, text="Move",command=lambda: ScreensTwo().make_secondframe(frame=self.win.topframe)).pack()
self.win.finish()
class ScreensTwo:
""" make windows and pulldown menu """
def __init__(self):
self.win = None
def pulldown_menu(self):
""" create a pulldown menu, and add it to the menu bar """
menubar = Menu(self.win.topframe)
basic_menu = Menu(menubar, tearoff=0)
menubar.add_cascade(label="Second File", menu=basic_menu)
basic_menu.add_command(label="print good bye", command=lambda: print("good bye"))
root.config(menu=menubar)
def make_secondframe(self, frame=None):
""" master method for controlling methods in class """
self.win = MakeWindow()
self.win.create(frame) # create the window
self.pulldown_menu()
mainframe = Frame(self.win.body)
mainframe.pack()
Label(mainframe, text="Second Frame: menu bar should have 'Second File' option.").pack()
Button(mainframe, text="Back", command=lambda: Screens().make_mainframe(frame=self.win.topframe)).pack()
self.win.finish()
mousewheel = -1
root = Tk() # initialize root window
position_x = 100 # initialize position and size for root window
position_y = 50
size_x = 625
size_y = 600
root.geometry("%dx%d+%d+%d" % (size_x, size_y, position_x, position_y))
root.title("Menu Bar")
Screens().make_mainframe()
