Object-Oriented Programming/GUI Applications/Menus

"""This program demonstrates tkinter menus.

Input:
    None

Output:
    Window with menus

References:
    https://www.geeksforgeeks.org/right-click-menu-using-tkinter/
    http://effbot.org/tkinterbook/tkinter-events-and-bindings.htm
    https://www.tutorialspoint.com/python/python_gui_programming.htm
    https://www.python-course.eu/python_tkinter.php
"""

import tkinter


class Root(tkinter.Tk):
    """Creates root window."""

    _main_menu = None
    _label = None

    def __init__(self, *args, **kwargs):
        tkinter.Tk.__init__(self, *args, **kwargs)

        self.title("tkinter Menu Example")
        self.geometry("%dx%d+0+0" % self.maxsize())

        self._main_menu = MainMenu(self)
        self._label = Label(self)
        self._label.pack()


class MainMenu(tkinter.Menu):
    """Creates Main menu."""

    @property
    def root(self):
        return self._root

    def __init__(self, root, *args, **kwargs):
        tkinter.Menu.__init__(self, root, *args, **kwargs)
        self._root = root

        file_menu = FileMenu(self, tearoff=0)
        self.add_cascade(label="File", menu=file_menu)

        root.config(menu=self)


class FileMenu(tkinter.Menu):
    """Creates File menu."""

    def __init__(self, *args, **kwargs):
        tkinter.Menu.__init__(self, *args, **kwargs)
        self.add_command(label="Exit", command=self.master.quit)


class Label(tkinter.Label):
    """Creates label with popup menu."""

    _menu = None

    def __init__(self, *args, **kwargs):
        tkinter.Label.__init__(self, *args, **kwargs,
            text="Right-click to display menu",
            width=320,
            height=240)

        self._menu = PopupMenu(self)
        # Some systems use button 2, some use button 3.
        # Binding to both.
        self.bind("<Button-2>", self._menu.popup)
        self.bind("<Button-3>", self._menu.popup)


class PopupMenu(tkinter.Menu):
    """Creates popup menu."""

    def __init__(self, *args, **kwargs):
        tkinter.Menu.__init__(self, *args, **kwargs,
            tearoff=0)

        self.add_command(label="Item 1", command=None)
        self.add_command(label="Exit", command=exit)

    def popup(self, event):
        try:
            self.tk_popup(event.x_root, event.y_root)
        finally:
            self.grab_release()


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