如何在Tkinter应用程序的每一帧上创建菜单

时间:2018-01-19 20:37:16

标签: python tkinter

我知道如何创建基本的Tkinter菜单栏,但我不知道如何实现它,以便菜单出现在多帧GUI的每一帧上。

我将使用菜单栏在帧之间切换。因此,我需要在菜单命令中运行controller.show_frame命令。我目前正在使用按钮来执行此操作。

我无法找到这样做的方法,因为(据我所知)菜单必须在框架类而不是tk.Tk类中创建,以便允许我运行该功能。

这是代码:

""" Messing about with tkinter """
import tkinter as tk
LARGE_FONT = ("Verdana", 12)

class Window(tk.Tk):
    """ Main class """

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

        container = tk.Frame(self)
        container.pack(side="top", fill="both", expand=True)
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        self.frames = {}

        for frame in (Main, Checker):
            current_frame = frame(container, self)
            self.frames[frame] = current_frame
            current_frame.grid(row=0, column=0, sticky="nsew")

        self.show_frame(Main)

    def show_frame(self, cont):
        """ Raises a particular frame, bringing it into view """

        frame = self.frames[cont]
        frame.tkraise()

def qprint(quick_print):
    """ Function to print a string """
    print(quick_print)

class Main(tk.Frame):
    """ Main frame of program """

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        label = tk.Label(self, text="Main Menu", font=LARGE_FONT)
        label.pack(pady=10, padx=10)

class Checker(tk.Frame):
    """ Password Strength Checker """

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        label = tk.Label(self, text="Password Checker", font=LARGE_FONT)
        label.pack(pady=10, padx=10)


APP = Window()
APP.geometry("350x200")
APP.mainloop()

2 个答案:

答案 0 :(得分:2)

  

“必须在框架类而不是tk.Tk类中创建菜单,以便允许我运行   功能“。

我不认为这是真的,请参阅下面为Menu小部件创建Toplevel的示例:

import tkinter as tk


if __name__ == '__main__':
    root = tk.Tk()
    root.withdraw()

    toplevel = tk.Toplevel(root)

    # create a toplevel menu
    menubar = tk.Menu(toplevel)
    menubar.add_command(label="Hello!")
    menubar.add_command(label="Quit!", command=root.quit)

    # display the menu
    toplevel.config(menu=menubar)

    root.mainloop()

或者,你可以在的框架中为创建菜单,条件是他们的父母是Toplevel - 就像。

在下面的示例中,当选择菜单项时,Root的菜单会在Root的菜单及其子FrameWithMenu对象的菜单之间跳转:

import tkinter as tk


class Root(tk.Tk):
    def __init__(self):
        super().__init__()

        self.title("The Root class with menu")
        self.a_frame = FrameWithMenu(self)
        self.create_menu()

    def create_menu(self):
        self.menubar = tk.Menu(self)
        self.menubar.add_command(label="Root", command=self.a_frame.replace_menu)
        self['menu'] = self.menubar



class FrameWithMenu(tk.Frame):
    def __init__(self, master):
        super().__init__(master)

    def replace_menu(self):
        """ Overwrite parent's menu if parent's class name is in _valid_cls_names.
        """

        _parent_cls_name = type(self.master).__name__
        _valid_cls_names = ("Tk", "Toplevel", "Root")
        if _parent_cls_name in _valid_cls_names:
            self.menubar = tk.Menu(self)
            self.menubar.add_command(label="Frame", command=self.master.create_menu)
            self.master['menu'] = self.menubar


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

答案 1 :(得分:1)

我找到了自己问题的答案。我需要做的就是使用controller参数创建菜单,该参数引用tk.Tk类。

class Main(tk.Frame):
    """ Main frame of program """

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        label = tk.Label(self, text="Main Menu", font=LARGE_FONT)
        label.pack(pady=10, padx=10)

        menubar = tk.Menu(controller)
        menubar.add_command(label="Checker", command=lambda: controller.show_frame(Checker))
        controller.config(menu=menubar)