2

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

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()

由创建的顶层窗口中的菜单按钮调出的菜单最初的行为与预期相同。单击此处的“新窗口”命令会创建一个新的此类窗口,该窗口的行为也符合预期。事实上,只要您继续创建新的顶级窗口,一切都会继续按预期工作。但是,一旦您删除(关闭)这些窗口中的任何一个,那么在随后创建的新窗口中,新菜单上的选项级联将不起作用。(在关闭之前创建的窗口中仍然可以。)

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

4

1 回答 1

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(及其选项)的代码放在__init__Top 的方法中。这样,每次调用 Top 时,都会存在 check_menu。

希望这会有所帮助(并且我已经充分解释了它:)

于 2013-07-10T15:59:33.950 回答