在Tkinter应用中什么时候需要调用mainloop?
我看到的每个关于tkinter的教程都说必须调用tkinter.mainloop
,这样窗口才能显示出来,事件才能被处理。他们在所有的例子中,包括简单的“你好,世界”程序里,都会调用这个函数。然而,当我在交互式命令行中试这些代码时,窗口却能正常显示,根本不需要调用mainloop。这个例子展示了如何在tkinter中嵌入matplotlib图形,创建了一个相对复杂的应用程序,里面有按钮可以平移、缩放和调整图表的大小,同样的,如果我去掉mainloop的调用,在交互式命令行中运行代码,这一切也都能正常工作。当然,如果我在交互式命令行外运行这个脚本(去掉mainloop),程序结束得太快,根本看不到发生了什么,但如果我加上input
来让程序保持打开状态,一切又都能正常工作(我在linux上运行的是python 3.2.2)。
那么,mainloop到底是干什么的,什么时候需要调用它呢?
编辑:为了更清楚,如果我打开GNOME终端并输入
$python3
>>> import tkinter
>>> root = tkinter.Tk()
一个窗口立刻就会出现,而不需要调用mainloop,而且更复杂的tkinter功能似乎也能正常工作(比如,往窗口里添加按钮)。在IDLE中,调用mainloop是必须的。我原本以为在调用mainloop之前,什么都不会被绘制,也不会处理任何事件。
6 个回答
当你运行你的代码时,如果没有一个叫做 mainloop
的函数,tkinter 窗口就不会打开。
比如说,下面的代码是不能工作的:
from tkinter import*
root=Tk()
但是,下面的代码就可以正常工作:
from tkinter import*
root=Tk()
root.mainloop()
想象一下,一个有互动界面的程序和一个计算第100个斐波那契数的程序。后者的程序只需要按照固定的步骤,从上到下依次执行。这些步骤和顺序是事先确定好的,不管你运行多少次,都是一样的。
但是,互动界面的程序就不一样了:在任何时刻,它都需要处理各种不同的事件和用户的操作。为了实现这个功能,程序通常会用到一个叫做“事件循环”的东西。事件循环是程序的核心控制结构,它会一直等待某个事件发生,然后再去执行相应的处理程序。
你没有提到你使用的是哪个互动命令行,但我猜是IDLE。IDLE本身就是一个Tkinter程序,它已经在运行一个事件循环。所以你在命令行中输入的Tkinter代码可能是绑定到了IDLE的事件循环上。
你主要的问题的答案是,你必须在准备好让你的应用程序运行时,调用一次且仅一次 mainloop
。
mainloop
实际上就是一个无限循环,简单来说,它的工作方式大概是这样的(这里的名字只是为了说明,并不是实际的方法名):
while True:
event=wait_for_event()
event.process()
if main_window_has_been_destroyed():
break
在这个上下文中,“事件”指的是用户的互动(比如鼠标点击、键盘按键等),还有来自工具包或操作系统/窗口管理器的请求,用来绘制或重新绘制一个小部件。如果这个循环没有运行,事件就不会被处理。如果事件不被处理,屏幕上就不会显示任何东西,而且你的程序可能会退出,除非你自己有一个无限循环在运行。
那么,为什么不需要交互式地调用这个呢?这是为了方便,因为一旦你调用了 mainloop
,就无法输入任何命令,因为 mainloop
会一直运行,直到主窗口被关闭。