我一直在尝试使用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()
mainloop
为您的tk.Tk()
应用程序输入事件监听循环。
您应该在每个tkinter应用程序中只使用Tk()创建一个对象。
现在,这个循环将“全局”侦听GUI事件,并将调用您注册的回调(事件处理程序)。在mainloop
调用之前的代码将运行,但在您调用之前,屏幕上不会显示或更新任何内容。在此之前,没有事件(用户输入,鼠标移动,键盘等)将排队并响应。但是小部件已创建和配置,但尚未显示。如果你在没有进入主循环的情况下调用root.update()
,你最终会看到窗口闪烁并消失,因为一切都在运行,你强制窗口刷新,但突然程序结束。
所以配置你的GUI,最后总是运行root.mainloop()
现在当你调用wait_window
时,你正在创建一个本地事件循环(如果它正在运行则阻塞主循环)。关于wait_window
的完美解释,Brian见here
你怎么了,你的应用程序很高兴与你的本地事件循环一起运行,但没有mainloop。这将是一件奇怪的事情。即使你正在布莱恩解释一个模态窗口,你想在窗口关闭后“返回”到主循环。
至于after
方法,它只是注册一个回调函数,在你选择的时间之后运行,或者在mainloop因为空闲之后运行after_idle
(没有更多的东西要刷新,队列中没有事件......,也要尽快考虑)。如果你想以同样的方式重新运行该函数,它应该在返回之前重新注册after
或after_idle
。
所以总是使用你的mainloop()
结束调用 - 或者我应该说事件循环开始调用:)
编辑:
此外,不要在代码中执行缓慢或可能阻塞循环的操作,例如调用sleep或任何其他阻塞函数。这将冻结GUI,直到块结束。