我什么时候需要在Tkinter应用程序中调用mainloop?

时间:2011-12-30 19:27:44

标签: python tkinter

每个tkinter教程我都看到声称必须调用tkinter.mainloop来绘制窗口和要处理的事件,并且它们总是调用此函数,即使在hello world程序中也是如此。但是,当我在交互式shell中尝试这些时,无需调用mainloop即可正确绘制窗口。在tkinter中嵌入matplotlib图形的This example会产生一个相对复杂的应用程序,其中包含用于在tkinter窗口内平移,缩放和调整绘图大小的按钮,如果删除对mainloop的调用并运行代码,这一切都有效。交互式shell。当然,如果我在交互式shell之外运行脚本(删除了mainloop),程序结束得太快就看不到会发生什么,但是如果我添加一个调用input来保持程序打开一切正常(我在Linux上运行python 3.2.2。

那么mainloop究竟做了什么,何时需要调用它?

编辑: 为了澄清,如果我打开GNOME终端并输入

$python3
>>> import tkinter
>>> root = tkinter.Tk()

一个窗口立即出现,而不必调用mainloop,更复杂的tkinter功能似乎也可以工作(例如,向窗口添加按钮)。在IDLE中,需要调用mainloop。我的理解是,在调用mainloop之前,不应绘制任何内容,也不应处理任何事件。

5 个答案:

答案 0 :(得分:44)

您的主要问题的答案是,当您准备好运行应用程序时,必须只调用一次mainloop。

mainloop只是一个看起来大致如此的无限循环(那些不是方法的实际名称,这些名称仅用于说明这一点):

while True:
    event=wait_for_event()
    event.process()
    if main_window_has_been_destroyed(): 
        break

在此上下文中,“事件”表示用户交互(鼠标单击,按键等)以及来自工具箱或OS /窗口管理器的绘制或重绘窗口小部件的请求。如果该循环未运行,则不会处理事件。如果事件没有得到处理,屏幕上不会显示任何内容,除非你有自己的无限循环运行,否则你的程序可能会退出。

那么,为什么你不需要以交互方式调用它?这只是一个方便,因为否则一旦你调用mainloop就不可能输入任何命令,因为mainloop运行直到主窗口被销毁。

答案 1 :(得分:7)

将程序与交互式GUI比较为计算第100个斐波纳契数的程序。所有后一个程序都必须按顺序从上到下进行一系列步骤。这组步骤及其顺序可以事先知道,无论你运行多少次,它都会保持不变。

但GUI程序是不同的:在任何特定时刻,它必须能够处理各种不同类型的事件和交互。此要求通常使用称为事件循环的编程构造来实现。事件循环是程序的中央控制结构。它等待事件发生,然后调度适当的处理程序。

你没有提到你正在使用哪个交互式shell,但我猜它是IDLE。 IDLE本身是一个Tkinter程序,它已经有一个事件循环。因此,您在shell中键入的Tkinter代码可能会绑定到IDLE的事件循环。

答案 2 :(得分:0)

执行代码时,tkinter窗口将拒绝打开而没有import pandas as pd pd.Series(['f.o', 'fuz', np.nan]).str.replace('f.', 'ba', regex=False) 函数。

例如,这将不起作用:

mainloop

这将起作用:

from tkinter import*
root=Tk()

答案 3 :(得分:-3)

我已经决定,不是在我的脚本中的任何地方直接调用mainloop,而是将其添加为atexit的一部分 - 也就是说,当Python解释器决定它时#39;开始关闭的时间,它将进入Tk的主循环。这样就可以防止它完成关闭序列,直到用户实际告诉Tk退出(IE,在Mac上使用command-Q,或点击Windows中的红色X.)

from Tkinter import Tk
root = Tk()

import atexit
atexit.register(root.mainloop)

似乎没有必要从系统命令行调用mainloop。 Python解释器将在没有它的情况下继续运行,因为它等待您的进一步输入(直到您运行exit())。

答案 4 :(得分:-3)

如下:

from tkinter import *

tk = Tk()
canvas = Canvas(tk, width=500, height=500)
canvas.pack()
canvas.create_line(0, 0, 500, 500)

mainloop()