如果我想简单地用语句创建一个Tkinter GUI,我可以这样做:
from Tkinter import *
root = Tk()
root.title("Test Window")
tkFrame = Frame(root)
tkButton = Button(tkFrame)
[...]
然而,文档建议将Tkinter与类定义一起使用,为Frame小部件创建子类:
class App(Frame):
[...]
我想明白为什么会这样。为什么我们不能将Frame的容器,窗口子类化?看来这是第一个例子中的语句所做的,为什么不在类定义中呢?
编辑(遵循布莱恩奥克利的回答):
我想在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
子类一样,但是在最高级别?
答案 0 :(得分:4)
没有任何内容表明tkinter类必须从框架继承。您可以从任何tkinter小部件或任何其他类继承。如果您找到了另外说明的文档,那么该文档是错误的。使用Frame
是一个合乎逻辑的选择,因为它被设计为其他小部件的容器,但它不是唯一的选择。
我个人从框架继承,因为我发现它很方便。我的一些GUI需要能够打开多个相同的窗口。通过将我的主代码放在一个框架中,我可以通过创建框架的多个实例并将它们打包在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__
方法。
你问过工作的例子,这里有几个:
您可能还想阅读问题Inheriting from Frame or not in a Tkinter application
中的回复