pythonpython-3.xooptkintertk-toolkit

How to create OOP based MenuBar with Tkinter


How to create OOP based MenuBar with Tkinter

I am trying to make a GUI program using Tkinter which requires a lot of functions to be accessed from the menubar. but i cant find a way to pack those functions efficiently to each menu.

import tkinter as tk
class MainWindow(tk.Tk):
    def __init__(self):
        super().__init__()
        self.geometry('900x600')
        self.resizable(0, 0)
        self.InitContents()

    def InitContents(self):
        container = tk.Frame(self)
        container.pack(fill=tk.BOTH,expand=True)
        root_menu=tk.Menu(self)
        self.config(menu=root_menu)
        
        fileMenu = tk.Menu(root_menu)
        editMenu = tk.Menu(root_menu)
        viewMenu = tk.Menu(root_menu)
        settingMenu = tk.Menu(root_menu)
        root_menu.add_cascade(label='File',menu=fileMenu)
        root_menu.add_cascade(label='Edit',menu=editMenu)
        root_menu.add_cascade(label='View',menu=viewMenu)
        root_menu.add_cascade(label='Settings',menu=settingMenu)
        #
        #i need to add a lot of functions to respective Menus

if __name__ == "__main__":
    root = MainWindow()
    root.mainloop()

how do i put my class for menubar

class SomeClass:
    def __init__(self):
        #does something
        pass
    def open_file():
        pass
    def save_file():
        pass
    def redo():
        pass
    def exit():
        pass
    #etc.....

Solution

  • You can subclass the tk.Menu widget class and use it as the MenuBar, then you would simply create each of the menus just like you are already doing and connect their callback commands in the same way but using the MenuBar class.

    This example is partially adapted from your code and partially from this page

    # which are needed
    from tkinter import *
    from tkinter.ttk import *
    import tkinter as tk
    
    class MenuBar(tk.Menu):
        def __init__(self, root):
            super().__init__(root)
            self.fileMenu = tk.Menu(self)
            self.editMenu = tk.Menu(self)
            self.viewMenu = tk.Menu(self)
            self.settingMenu = tk.Menu(self)
            self.fileMenu.add_command(label ='New File', command = self.new_file)
            self.fileMenu.add_command(label ='Open...', command = self.open_file)
            self.fileMenu.add_command(label ='Save', command = self.save_file)
            self.fileMenu.add_separator()
            self.fileMenu.add_command(label ='Exit', command = root.destroy)
            self.editMenu.add_command(label ='Cut', command = None)
            self.editMenu.add_command(label ='Copy', command = None)
            self.editMenu.add_command(label ='Paste', command = None)
            self.editMenu.add_command(label ='Select All', command = None)
            self.editMenu.add_separator()
            self.editMenu.add_command(label ='Find...', command = None)
            self.editMenu.add_command(label ='Find again', command = None)
            self.viewMenu.add_command(label ='Tk Help', command = None)
            self.viewMenu.add_command(label ='Demo', command = None)
            self.viewMenu.add_separator()
            self.viewMenu.add_command(label ='About Tk', command = None)
            self.add_cascade(label='File',menu=self.fileMenu)
            self.add_cascade(label='Edit',menu=self.editMenu)
            self.add_cascade(label='View',menu=self.viewMenu)
            self.add_cascade(label='Settings',menu=self.settingMenu)
    
        def open_file(self):
            ...
    
        def save_file(self):
            ...
    
        def redo(self):
            ...
    
        def new_file(self):
            ...
    
    
    class MainWindow(tk.Tk):
        def __init__(self):
            super().__init__()
            self.geometry('900x600')
            self.resizable(0, 0)
            container = tk.Frame(self)
            container.pack(fill=tk.BOTH,expand=True)
            root_menu=MenuBar(self)
            self.config(menu=root_menu)
    
    if __name__ == "__main__":
        root = MainWindow()
        root.mainloop()