在python中使用tkinter导致此级联菜单失败的原因是什么?

时间:2013-07-05 02:46:05

标签: python menu tkinter cascade

以下代码显示我不明白的问题:

from Tkinter import *
root = Tk()

cheese_var = IntVar()
parrot_var = IntVar(value=1)
check_menu = Menu(tearoff=0)
check_menu.add_checkbutton(label="Cheese", variable=cheese_var)
check_menu.add_checkbutton(label="Parrot", variable=parrot_var)
count = 0

class Top():
    def __init__(self):
        global count
        count += 1
        self.tl = Toplevel(root)
        Label(self.tl, text="Window " + str(count)).pack()
        self.mb = Menubutton(self.tl, text="Push Me", bg='pink')
        self.menu = Menu(self.mb, tearoff=0)
        self.menu.add_cascade(label="Choices", menu=check_menu)
        self.menu.add_command(label="New Window", command=new_top)
        self.mb.config(menu=self.menu)
        self.mb.pack()

def new_top():
    Top()

Top()
root.mainloop()

创建的顶级窗口中的菜单按钮启动的菜单最初表现如预期。单击New Window命令可以创建一个新的窗口,它也可以按预期运行。实际上,只要你不断创建新的顶级窗口,一切都会按预期继续工作。但是,一旦删除(关闭)其中任何一个窗口,则在随后创建的新窗口中,新菜单上的“选择”级联不起作用。 (在关闭之前创建的窗口中它仍然可以。)

我最初遇到这种症状的情况要复杂得多,但我能够将其简化为上述展示问题的示例。我发现我可以通过让每个Top实例创建自己的check_menu作为属性来避免这个问题;但我不明白为什么这是必要的。如果没有这样的问题,请指出我的方法,如果没有复制多个窗口中使用的级联菜单。

1 个答案:

答案 0 :(得分:0)

不幸的是,我认为不可能做你想做的事。我会尽力解释。

首次运行脚本时,会创建check_menu并在第一个窗口中正常工作。当您创建更多窗口时,check_menu只是在它们之间共享。但是,当您关闭其中一个时,check_menu(及其下的所有内容)将被销毁。因此,当您在此之后创建新窗口时,check_menu不再存在且不显示。

但是,脚本不会抛出错误,因为由于某种原因,Tkinter允许您将菜单分配给非菜单的东西。信不信由你,没有以下代码:

self.menu.add_cascade(label="Choices", menu=None)
self.menu.add_cascade(label="Choices", menu=1)
self.menu.add_cascade(label="Choices", menu="")

将破坏脚本。除了创建一个空的级联“Choices”之外,每一行都什么都不做。

这基本上就是发生了什么。关闭一个窗口后,check_menu及其下的所有内容都将被销毁。然而,Tkinter并没有抛出错误,而是将菜单分配给不再是菜单的东西(就其分配菜单而言,我相信它使用的是check_menu的旧实例,它已被销毁)。

要解决此问题,请在每次调用Top时重新创建check_menu及其下的所有内容。换句话说,将check_menu(及其选项)的代码放在Top的__init__方法中。这样,每次调用Top时,都会存在check_menu。

希望这有帮助(我已经充分解释了这一点)。