我正在尝试学习 python、Tkinter 和 oop。下面是我在 effbot.org 上的教程之后编写的代码
from Tkinter import Tk, Frame, Label
class Nexus(object):
"""Top level object which represents entire app"""
def __init__(self, main_window):
self.nexus_frame = Frame(main_window)
self.nexus_frame.pack()
self.label = Label(main_window, text="Tkinter")
self.label.pack()
def main():
main_window = Tk()
nexus_app = Nexus(main_window)
main_window.wm_title("Hello World Window")
width = main_window.winfo_screenwidth()
height = main_window.winfo_screenheight()
main_window.wm_minsize(width=width-100, height=height-100)
main_window.mainloop()
if __name__ == "__main__":
main()
这里首先创建一个顶级窗口,并将其作为参数传递给 Nexus 类,我在其中添加一个框架和一个标签到该框架。然后我在主函数中设置相对于当前屏幕大小的顶级窗口的大小。
我的问题是为什么顶层窗口是在 main 函数中创建的?
它不能在 Nexus 类本身的 __init__
内部创建吗?
如果 main_window 在 Nexus 类的 __init__
中创建并在其中启动 mainloop()
会有什么区别?
最佳答案
一旦输入Tk.mainloop
,就不会再执行任何代码。相反,Tk
事件循环将接管(因此得名)。
这意味着,如果您做了这样的事情:
def main():
...
main_window.mainloop()
print 'Hello world!'
那么该 print 语句将永远不会被执行(或者至少在 GUI 运行时不会被执行)。
<小时/>那么,考虑到这一点,为什么在构造函数(__init__
语句)中创建根窗口和执行主循环会出现问题?嗯,有两个基本原因:
这意味着构造函数永远不会返回,这是意外的。如果程序员看到这个:
def main(): Nexus() print 'Hello world!'
然后他或她将期望执行打印语句。通常,您不会期望创建类的实例会导致无限循环(就像事件循环一样)。
与此相关的是第二个原因:不可能创建多个
Nexus
实例,因为一旦创建一个,Tk.mainloop
将接管。同样,这是出乎意料的:类是一种对象类型的描述,您通常希望能够实例化多个这样的对象。此时,如果你写:
def main(): ... Nexus(main_window) Nexus(main_window)
然后您将在屏幕上看到
Nexus
窗口的两个副本。这是意料之中的,也是合理的。另一种选择则不然。
那么要点是什么?
当您处理 GUI 程序时,进入事件循环是您最不想做的事情。您的设置可能涉及创建一个对象(如现在),也可能涉及创建许多对象(例如,复杂的 GUI 应用程序可能有两个或三个窗口)。
因为我们希望能够在这两种情况下编写类似的代码,所以通常的方法是创建根窗口(Tk
对象)一次,然后将其作为对任何需要了解它的类。
关于Python 和 Tkinter : object oriented programming query,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27764418/