Python:为啥 Tkinter 类实例化必须使用 Frame?
Posted
技术标签:
【中文标题】Python:为啥 Tkinter 类实例化必须使用 Frame?【英文标题】:Python: why must Tkinter class instantiation use a Frame?Python:为什么 Tkinter 类实例化必须使用 Frame? 【发布时间】:2015-12-29 06:33:18 【问题描述】:如果我想简单地用语句创建一个 Tkinter GUI,我可以这样做:
from Tkinter import *
root = Tk()
root.title("Test Window")
tkFrame = Frame(root)
tkButton = Button(tkFrame)
[...]
然而,文档建议将 Tkinter 与类定义一起使用,子类化 Frame 小部件:
class App(Frame):
[...]
我想了解为什么会这样。为什么我们不能子类化 Frame 的容器,即窗口?看起来这就是第一个示例中的语句所做的,那么为什么不在类定义中呢?
编辑(按照 Bryan Oakley 的回答):
我想在 Tkinter 的***别进行实例化,我认为它是 Tk()(虽然我遇到过引用说 Frame 是***别,但没关系)。实际上,以下将创建一个窗口:
from Tkinter import *
class Application(Tk):
pass
app = Application()
app.mainloop()
...但是当我尝试添加小部件时,我会收到错误或两个窗口,小部件位于新窗口中,具体取决于我如何构建代码。这是一个基本示例,它将生成带有按钮的第二个窗口:
from Tkinter import *
class Application(Tk):
tkBtn = Button()
tkBtn.pack()
app = Application()
app.mainloop()
使用self
、__init__
等会产生错误。有人可以指出我在***别实例化 Tkinter 的工作代码吗?就像我看到的所有 Frame
子类一样,但在***别?
【问题讨论】:
您遇到的任何引用说明Frame
是“Tkinter 的***别”都是错误的。
【参考方案1】:
没有什么说 tkinter 类必须从框架继承。您可以从任何 tkinter 小部件或任何其他类继承。如果您找到了另有说明的文档,则该文档是错误的。使用Frame
是一个合乎逻辑的选择,因为它被设计为其他小部件的容器,但它不是唯一的选择。
我个人从框架继承,因为我觉得它很方便。我的一些 GUI 需要能够打开多个相同的窗口。 通过将我的主要代码放在 Frame
中,我可以创建多个窗口,只需创建框架的多个实例,并将它们打包到 Toplevel
小部件中。
当您从Tk
继承时,您只能拥有一个实例。在现实世界中,这通常就足够了,这样做绝对没有错。因为我个人编写了相当多的 tkinter 程序,所以让它们都以完全相同的方式开始对我来说很方便。
另一个不错的选择是Canvas
,因为您可以轻松添加背景图片,而Frame
则无法做到这一点。
底线:您绝对不需要从 Frame 继承。继承你想要的任何东西。
(以下是针对原始问题的编辑而编写的)
参考此代码:
from Tkinter import *
class Application(Tk):
tkBtn = Button()
tkBtn.pack()
app = Application()
app.mainloop()
您看到两个窗口的原因是您没有正确创建类。在创建小部件之前,您需要调用超类的__init__
方法,因为这实际上是创建根窗口的方法。因为你不这样做,所以你最终会得到两个窗口。当您将一个按钮添加到尚未构建的根窗口时,您会得到一个隐式创建的,当您的子类完成初始化时,您会得到另一个。
解决办法是不走捷径,而是正确初始化类:
from Tkinter import *
class Application(Tk):
def __init__(self):
Tk.__init__(self)
tkBtn = Button()
tkBtn.pack()
app = Application()
app.mainloop()
请注意,这不是特定于 tkinter 的问题。子类化时,除非有明确的理由,否则应始终调用超类的__init__
方法。
您要求提供工作示例,这里有几个:
https://***.com/a/22424245/7432 https://***.com/a/11405393/7432您可能还想阅读问题Inheriting from Frame or not in a Tkinter application中的回复
【讨论】:
@DhaLee:我已经更新了我的答案以解决您的其他问题。以上是关于Python:为啥 Tkinter 类实例化必须使用 Frame?的主要内容,如果未能解决你的问题,请参考以下文章