Python:为什么 Tkinter 类实例化必须使用 Frame?

X-M*_*ann 5 python class tkinter

如果我想简单地用语句创建一个 Tkinter GUI,我可以这样做:

from Tkinter import *
root = Tk()
root.title("Test Window")
tkFrame = Frame(root)
tkButton = Button(tkFrame)
[...]
Run Code Online (Sandbox Code Playgroud)

但是,文档建议将 Tkinter 与类定义一起使用,子类化 Frame 小部件:

class App(Frame):
  [...]
Run Code Online (Sandbox Code Playgroud)

我想了解为什么会这样。为什么我们不能子类化 Frame 的容器,即窗口?似乎第一个例子中的语句就是这样做的,那么为什么不在类定义中呢?

编辑(按照 Bryan Oakley 的回答):

我想在 Tkinter 的最高级别进行实例化,我假设它是 Tk() (虽然我遇到过说明 Frame 是顶级的引用,但没关系)。实际上,以下将创建一个窗口:

from Tkinter import *
class Application(Tk):
  pass
app = Application()
app.mainloop()
Run Code Online (Sandbox Code Playgroud)

...但是一旦我尝试添加小部件,我就会收到错误或两个窗口,小部件在一个新窗口中,具体取决于我如何构建代码。这是一个基本示例,它将生成带有按钮的第二个窗口:

from Tkinter import *
class Application(Tk):
  tkBtn = Button()
  tkBtn.pack()
app = Application()
app.mainloop()
Run Code Online (Sandbox Code Playgroud)

使用self__init__等的任何更多内容都会产生错误。有人可以指出我在最高级别实例化 Tkinter 的工作代码吗?就像Frame我看到的所有子类一样,但在最高级别?

Bry*_*ley 5

没有什么说 tkinter 类必须从框架继承。您可以从任何 tkinter 小部件或任何其他类继承。如果您发现文档另有说明,则该文档是错误的。使用Frame是一个合乎逻辑的选择,因为它被设计为其他小部件的容器,但它不是唯一的选择。

我个人从框架继承,因为我觉得它很方便。我的一些 GUI 需要能够打开多个相同的窗口。通过将我的主要代码放在 a 中,Frame我可以通过创建框架的多个实例并将它们打包到Toplevel小部件中来创建多个窗口

当您从 继承时Tk,您只能拥有一个实例。在现实世界中,这通常就足够了,这样做绝对没有错。由于我个人编写了相当多的 tkinter 程序,让它们开始时完全相同对我来说很方便。

另一个不错的选择是 ,Canvas因为您可以轻松添加背景图像,而使用Frame.

底线:你绝对不会要求从框架继承。继承任何你想要的。


(以下内容是针对对原始问题的编辑而编写的)

参考此代码:

from Tkinter import *
class Application(Tk):
  tkBtn = Button()
  tkBtn.pack()
app = Application()
app.mainloop()
Run Code Online (Sandbox Code Playgroud)

您看到两个窗口的原因是您没有正确创建类。您需要__init__在创建小部件之前调用超类的方法,因为这才是真正创建根窗口的内容。因为你不这样做,你最终有两个窗口。当您将按钮添加到尚未构建的根窗口时,您会得到一个隐式创建的,当您的子类完成初始化时,您会得到另一个。

解决方案是不要走捷径,而是正确初始化类:

from Tkinter import *
class Application(Tk):
    def __init__(self):
        Tk.__init__(self)
        tkBtn = Button()
        tkBtn.pack()
app = Application()
app.mainloop()
Run Code Online (Sandbox Code Playgroud)

请注意,这不是特定于 tkinter 的问题。在子类化时,除非您有明确的理由不这样做,否则您应该始终调用__init__超类的方法。

您要求提供工作示例,这里有几个:

您可能还想阅读Inheriting from Frame or not in a Tkinter application问题中的回答