Tkinter网格管理器无法管理"顶级窗口"菜单



所以我有一个Python 3和Tkinter应用程序。我目前正试图在弹出窗口的顶部添加一个菜单栏。创建它很好,但一旦我尝试grid(),它就会失控,并给我带来以下错误:

[first line omitted]
File "C:UsersMeDocumentssync.py", line 13 in __init__
  self.createWidgets()
File "C:UsersMeDocumentssync.py", line 21, in createWidgets
  self.menubar.grid(column = 0, comlumnspan = 3)
File "C:Program Files (x86)Python34libtkinter__init__.py", line 2020, in grid_configure + self._options(cnf,kw))
_tkinter.TclError: can't manage ".41452544.49048880": it's a top-level window

因此,很明显,流正在工作:__init__调用createWidgets创建self.menubar,添加子菜单,调用self.menubar.grid

我不明白的是,为什么Tkinter认为它被调用到网格的菜单栏是一个顶级窗口。跟踪中列出的self.menubar.grid()显然是问题的原因,而不是根窗口,所以它一定是这么想的。

以下是有问题的代码:

def createWidgets(self):
    self.menubar = tk.Menu(self)
    self.menubar.grid(column = 0, columnspan = 3)
    SyncMenu = tk.Menu(self.menubar, tearoff = 0)
    SyncMenu.add_command(label = "Connect", command = self.Sync.Connect)
    SyncMenu.add_command(label = "Disconnect", command = self.Sync.Disconnect)
    FileMenu = tk.Menu(self.menubar, tearoff = 0)
    FileMenu.add_command(label = "Upload File", command = self.File.Upload)
    FileMenu.add_command(label = "Browse Online Files", command = self.File.Browse)
    self.menubar.add_cascade(label = "Sync", menu = SyncMenu)
    self.menubar.add_cascade(label = "File", menu = FileMenu)

无论我把呼叫放到grid()的哪个位置,都会出现相同的错误。

这个问题的另一部分是,我使用的是Python3和更新的Tkinter,所以我没有tk.Tk()

class Application(tk.Frame):
    def __init__(self, master=None):
        tk.Frame.__init__(self,master)
        self.grid()
        self.createWidgets()
        self.master.geometry("500x500")

您不能在菜单上使用网格。Tkinter认为它们是顶级窗口,因为它们漂浮在其他窗口之上。

创建传统菜单栏的正常方法是将其与根窗口的menu属性相关联:

root = tk.Tk()
menubar = tk.Menu(root)
...
root.configure(menu=menubar)

我已经想通了。当我编辑问题以添加第二个代码块时,我注意到self.master.geometry行,我想"那行会影响主窗口,我不能使用它吗?"

答案是肯定的,所以找到根窗口的解决方案就是使用self.master,它在我的__init__方法中由tk.Frame.__init__:的超级调用定义

class Application(tk.Frame):
    def __init__(self, master=None):
        tk.Frame.__init__(self,master)    # This line defines self.master
        self.grid()
        self.createWidgets()
        self.master.geometry("500x500")   # This line uses it

因此,让我的菜单栏进入正确窗口的解决方案是:

self.master["menu"] = self.menubar

其在创建所有菜单和菜单项之后在代码中。

最新更新