简体   繁体   English

Tkinter网格管理器无法管理“顶层窗口”菜单

[英]Tkinter grid manager can't manage 'top level window' menu

So I've got a Python 3 and Tkinter app. 所以我有一个Python 3和Tkinter应用程序。 I'm currently trying to add a menu bar to the top of the window it pops up in. It's fine creating, but as soon as I try to grid() it, it all goes haywire and throws me this error: 我目前正在尝试在弹出窗口的顶部添加一个菜单栏。创建起来很好,但是一旦我尝试将它grid()起来,一切就变得一团糟,并向我抛出此错误:

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

So from that, it's fairly obvious that the flow is working: __init__ calls createWidgets creates self.menubar , adds submenus, calls self.menubar.grid . 因此,由此可见,该流程正在正常工作: __init__调用createWidgets创建self.menubar ,添加子菜单,调用self.menubar.grid

What I can't figure out is why Tkinter thinks the menubar it's being called to grid is a top-level window. 我不明白的是,为什么Tkinter认为被称为网格的菜单栏是顶层窗口。 self.menubar.grid() , being listed in the trace, is clearly the cause of the problem rather than the root window, so that must be what it's thinking. 在跟踪中列出的self.menubar.grid()显然是问题的原因,而不是根窗口,因此这一定是它的想法。

Here's the bit of code in question: 这是有问题的代码:

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)

The same error comes up no matter where I put the call to grid() . 无论我在哪里调用grid()都会出现相同的错误。

The other part of this problem is that I'm in Python 3 and the updated Tkinter, so no tk.Tk() for me. 这个问题的另一部分是我使用的是Python 3和更新的Tkinter,所以对我来说没有tk.Tk() Instead, to initialise, I have this: 相反,要初始化,我有这个:

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

You can't use grid on menus. 您不能在菜单上使用网格。 Tkinter considers them a top-level window because they float above other windows. Tkinter认为它们是顶级窗口,因为它们漂浮在其他窗口之上。

The normal way to create a traditional menubar is to associate it with the menu attribute of the root window: 创建传统菜单栏的通常方法是将其与根窗口的menu属性相关联:

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

I've figured it out. 我知道了。 When I edited the question to add the second code block, I noticed the self.master.geometry line, to which I thought "That line affects the main window, couldn't I use that?" 当我编辑问题以添加第二个代码块时,我注意到self.master.geometry行,我认为“该行会影响主窗口,我不能使用它吗?”

The answer was yes, so the solution to finding the root window was just to use self.master , which is defined in my __init__ method by the supercall to tk.Frame.__init__ : 答案是肯定的,因此找到根窗口的解决方案只是使用self.master ,它是在我的__init__方法中通过对tk.Frame.__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

So the solution to get my menubar into the correct window is now this: 因此,使菜单栏进入正确窗口的解决方案是:

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

which is in the code after creating all the menu and menu items. 创建所有菜单和菜单项之后的代码中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM