Tkinter启用/禁用菜单。

18

我需要帮助。 我希望用户登录... 一旦他登录了,只有他被允许访问的模块对应的菜单才会被启用。 因此,我需要在开始时禁用所有菜单(除了“文件”和“帮助”)... 并且我需要在登录后启用相应的菜单...

登录代码尚未编写.. 我只是想看看如何实现... 下面是我的代码:

import Tkinter as tk

class gv:
    w = 800
    h = 500
    title = 'gsm ...'
    MDLS =   [['File','Settings','_s','Quit'],
            ['main menu','mm1','mm2'],
            ['second menu','sm1','sm2','sm3'],
            ['Help','About']]

class GammaSoft(tk.Frame):
    def __init__(self, master):
        tk.Frame.__init__(self, master, width=gv.w, height=gv.h)
        self.master.title(gv.title)
        self.master.resizable(0,0)
        self.pack_propagate(0)
        self.pack()

        menu_bar = tk.Menu()
        self.nMenu = []
        mc = 0
        for MDL in gv.MDLS:
            self.nMenu.append(tk.Menu(menu_bar, tearoff=0))
            for itm in MDL[1:]:
                if itm == '_s':
                    self.nMenu[mc].add_separator()
                else:
                    self.nMenu[mc].add_command(label=itm, command=lambda itm=itm: self.menu_call(itm))
            menu_bar.add_cascade(label=MDL[0], menu=self.nMenu[mc])
            mc += 1
        self.master.config(menu=menu_bar)

        frame1 = tk.Frame(self)
        frame1.pack()
        lblUsername = tk.Label(frame1, text='Username: ')
        lblPassword = tk.Label(frame1, text='Password: ')
        lblModule = tk.Label(frame1, text='Module: ')
        lblSpace1 = tk.Label(frame1, text='      ')
        lblSpace2 = tk.Label(frame1, text='      ')
        self.Username_var = tk.StringVar()
        self.txtUsername = tk.Entry(frame1, textvariable=self.Username_var, width=14)
        self.Password_var = tk.StringVar()
        self.txtPassword = tk.Entry(frame1, textvariable=self.Password_var, show="x", width=14)
        self.Module_var = tk.StringVar()
        options = [Li[0] for Li in gv.MDLS[1:len(gv.MDLS)-1]]
        self.Module_var.set(options[0])
        self.cmbModule = tk.OptionMenu(frame1, self.Module_var, *tuple(options))
        self.cmbModule.config(takefocus=1, width=14)
        self.btnLiLo = tk.Button(frame1, text='Log in', command=self.LiLo)

        lblUsername.pack(side=tk.LEFT)
        self.txtUsername.pack(side=tk.LEFT)
        lblSpace1.pack(side=tk.LEFT)
        lblPassword.pack(side=tk.LEFT)
        self.txtPassword.pack(side=tk.LEFT)
        lblSpace2.pack(side=tk.LEFT)
        lblModule.pack(side=tk.LEFT)
        self.cmbModule.pack(side=tk.LEFT)
        self.btnLiLo.pack(side=tk.RIGHT)

        separator = tk.Frame(self,height=2, bd=1, relief=tk.SUNKEN)
        separator.pack(fill=tk.X, padx=5, pady=5)

        frame2 = tk.Frame(self)
        frame2_up = tk.Frame(frame2)
        frame2_up.pack(fill=tk.X, side=tk.TOP)
        frame2_dn = tk.Frame(frame2)
        frame2_dn.pack(fill=tk.BOTH, side=tk.BOTTOM)

        lblFilter = tk.Label(frame2_up, text='Filter Text: ')
        lblAt = tk.Label(frame2_up, text='At: ')
        lblSpace3 = tk.Label(frame2_up, text='      ')
        self.Filter_var = tk.StringVar()
        self.txtFilter = tk.Entry(frame2_up, textvariable=self.Filter_var, width=14)
        self.At_var = tk.StringVar()
        self.cmbAt = tk.OptionMenu(frame2_up, self.At_var, '')
        self.cmbAt.config(takefocus=1, width=14)
        self.btnGo = tk.Button(frame2_up, text='Apply')
        self.btnClr = tk.Button(frame2_up, text='Clear')
        lblFilter.pack(side=tk.LEFT)
        self.txtFilter.pack(side=tk.LEFT)
        lblSpace3.pack(side=tk.LEFT)
        lblAt.pack(side=tk.LEFT)
        self.cmbAt.pack(side=tk.LEFT)
        self.btnClr.pack(side=tk.RIGHT)
        self.btnGo.pack(side=tk.RIGHT)

        frame2.pack(fill=tk.BOTH)
        self.log_out

    def log_out(self):
        pass

    def LiLo(self):
        pass

    def print_out(self):
        print('%s, %s!' % (self.greeting_var.get().title(), self.recipient_var.get()))

    def menu_call(self, data):
        print "Once more, clicked / commanded %s" % data

    def run(self):
        self.mainloop()

app = GammaSoft(tk.Tk())
app.run()

我注意到当我将级联菜单添加到menu_bar时,如果按照以下方式进行,则会使所有菜单都被禁用...menu_bar.add_cascade(label=MDL[0], menu=self.nMenu[mc], state=tk.DISABLED) - mlwn
我也可以使用以下代码...但我想禁用父级菜单,而不是逐个禁用子菜单项...self.nMenu[0].entrycget(0, 'label') self.nMenu[0].entryconfigure('Quit', state=tk.DISABLED) self.nMenu[0].entryconfigure(0) - mlwn
你有阅读菜单命令的文档,看看是否有禁用某些功能的方法吗?你做了哪些研究或尝试来解决这个问题? - Bryan Oakley
@BryanOakley,我唯一达到的地方是,如果我在创建期间禁用菜单,我可以访问“状态”..但是如果我稍后尝试使用nMenu [0] .config(state = tk.DISABLED)tk.NORMAL...我会收到一个错误_tkinter.TclError:unknown option "-state"...我正在尝试从我拥有的文档中阅读更多内容..但是没有运气...如果您能为我澄清这个想法,我将不胜感激...我希望您能理解我想做什么... - mlwn
3个回答

27

您可以通过启用或禁用与其相关联的菜单项来启用或禁用整个菜单。

以下是一个编造的示例。使用 Test1 菜单来启用或禁用 Test2 菜单。

import Tkinter as tk

class Example(tk.Frame):
    def __init__(self, root):
        tk.Frame.__init__(self, root)

        self.menubar = tk.Menu()
        self.test1Menu = tk.Menu()
        self.test2Menu = tk.Menu()
        self.menubar.add_cascade(label="Test1", menu=self.test1Menu)
        self.menubar.add_cascade(label="Test2", menu=self.test2Menu)

        self.test1Menu.add_command(label="Enable Test2", command=self.enable_menu)
        self.test1Menu.add_command(label="Disable Test2", command=self.disable_menu)
        self.test2Menu.add_command(label="One")
        self.test2Menu.add_command(label="Two")
        self.test2Menu.add_command(label="Three")
        self.test2Menu.add_separator()
        self.test2Menu.add_command(label="Four")
        self.test2Menu.add_command(label="Five")

        root.configure(menu=self.menubar)

    def enable_menu(self):
        self.menubar.entryconfig("Test2", state="normal")

    def disable_menu(self):
        self.menubar.entryconfig("Test2", state="disabled")

if __name__ == "__main__":
    root = tk.Tk()
    root.geometry("500x500")
    app = Example(root)
    app.pack(fill="both", expand=True)
    root.mainloop()

1
我现在明白解决方案是多么简单和直接了... :) 我还有一个问题... 是否可以禁用/启用一个框架?或者我应该逐个循环到其子项? - mlwn

1

您也可以使用以下方法...但我想禁用父菜单,而不是逐个禁用子项...

self.nMenu[0].entrycget(0, 'label')
self.nMenu[0].entryconfigure('Quit', state=tk.DISABLED) 
self.nMenu[0].entryconfigure(0)

0

要禁用菜单栏中的整个菜单,请编写以下代码:

menubar.entryconfig(1, state = DISABLED)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接