Tkinter MenuBar malfunctioning on Mac when switching frames

28 Views Asked by At

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()

enter image description here

0

There are 0 best solutions below