Tkinter代码在没有mainloop,更新或之后运行

时间:2017-12-22 15:35:48

标签: python tkinter python-3.6

我一直在尝试使用tkinter来制作一个gui来从这些文件中选择一些excel文件和工作表。

我在python方面有很多经验,但我可能会说tkinter的新手。

我编写的用于选择文件的代码如下所示(错别字可能是因为我无法在机器上访问这些文件所在的互联网,所以我在这里输入它。)

我的问题是关于mainloop(),更新功能和after()。我的代码末尾有mainloop(),但是我的程序在完成它的操作之后不会终止(即终端会保留)。所以我删除了mainloop(),现在它完全无需mainloop()update()after()来电。

我真的不明白这一点并且非常愿意。我得到mainloop()停止代码进行直到根关闭,但我认为没有mainloop()就会出现任何内容,并且此代码会等待用户在继续之前关闭窗口。

我也想知道如果我没有mainloop(或者类似),代码仍然会很好,无论我root.destroy()课程结束时是否App(在代码中评论)。我也没有。

这些信息有助于我在未来制作更好,更正确的代码,并希望能够改进这一代码。仅供参考,我在各处寻找答案,找不到一个,至少有一个我能理解的。非常感谢。

这是我能想到的最小代码。

代码(原始帖子编辑):

import tkinter as tk
from tkinter import ttk

class App:
    def __init__(self, parent):
        self.root = parent
        self.root.withdraw()

        tl = tk.Toplevel(parent)
        b = ttk.Button(tl, text="Test widget")
        b.grid()
        tl.wait_window()

        # This line does not change how the code functions at all
        #self.root.destroy()

    def run(self):
        # Whether or not this is a function in the class or called globally doesn't matter.
        self.root.mainloop()


if __name__ == "__main__":
    root = tk.Tk()
    app = App(root)

    # This is the mainloop() call. If I include it, the program does not close after
    # running the code in App.__init__. Without it, it runs perfectly.
    # app.run()

1 个答案:

答案 0 :(得分:0)

mainloop为您的tk.Tk()应用程序输入事件监听循环。

您应该在每个tkinter应用程序中只使用Tk()创建一个对象。

现在这个循环将“全局”侦听GUI事件,并将调用您注册的回调(事件处理程序)。 mainloop调用之前的代码将运行,但在您调用之前,屏幕上不会显示或更新任何内容。在此之前,没有事件(用户输入,鼠标移动,键盘等)将排队并响应。但是小部件已创建和配置,但尚未显示。如果你在没有进入主循环的情况下调用root.update(),你最终会看到窗口闪烁然后消失,因为一切都在运行,你强制窗口刷新,但突然程序结束了。

所以配置你的GUI,最后总是运行root.mainloop()

现在当你调用wait_window时,你正在创建一个本地事件循环(如果正在运行则阻塞主循环)。有关Brian wait_window的完整解释,请参阅here

你遇到的情况是你的应用程序很高兴与你的本地事件循环一起运行,但是没有mainloop。这将是一件奇怪的事情。即使你正在Brian解释一个模态窗口,你也想在窗口关闭后“返回”到主循环。

对于after方法,它只是注册一个回调函数,在你选择的时间之后运行,或者在主循环因为空闲之后运行after_idle(不再需要刷新,队列中没有事件)。 ..,也想尽快)。如果你想以同样的方式重新运行该功能,它应该在返回之前重新注册afterafter_idle

所以总是使用你的mainloop()结束通话 - 或者我应该说事件循环开始通话:)

编辑:

此外,不要在代码中执行缓慢或可能阻塞循环的操作,例如调用sleep或任何其他阻塞函数。这将冻结GUI,直到块结束。