Tkinter:一个或多个主循环?

1 投票
2 回答
2129 浏览
提问于 2025-04-17 02:45

我有一个已经很大的 Tkinter 程序,所以我有一个 init 文件,在里面定义了 root = Tk() 窗口(基本上包含一个 Text 组件和一些其他东西),还有一些代码,最后是调用 mainloop() 函数。

一切都正常,直到我需要在 mainloop 之前调用一个过程,并且我想在开始时弹出一个 wait 窗口,等过程结束后再关闭它。

我写了类似这样的代码:

msg = Message(root, text='wait a few seconds...')
msg.pack()

但是这样不行,也不能工作,因为 mainloop() 还没有被调用!

如果我改成这样:

msg = Message(root, text='wait a few seconds...')
msg.pack()
mainloop()

程序在第一个 mainloop 这里停住了,没法完成过程调用。

mainloop() 应该作为你程序的最后一行代码来使用,之后 Tkinter 程序就会根据用户的点击和互动来运行。

在这里,我需要一个顺序:弹出窗口 > 做事情 > 关闭窗口 > 进入主循环

2 个回答

0

你应该使用Tkinter的方法来运行asyncore的循环功能,但要用asyncore.poll(0)来代替asyncore.loop()。如果你每隔x毫秒调用一次asyncore.poll(0)这个函数,它就不会对Tkinter的主循环产生影响了。

1

你说得对,mainloop 这个方法需要在你的程序初始化完成后调用一次。这是为了启动事件循环,这样窗口才能自己绘制、响应各种事件等等。

你可以把初始化过程分成两个部分。第一部分是创建等待窗口,这个步骤是在启动事件循环之前完成的。第二部分是完成剩下的初始化,这个步骤是在事件循环启动后进行的。你可以通过 after 方法来安排第二个阶段的执行。

下面是一个简单的例子:

import Tkinter as tk
import time

class SampleApp(tk.Tk):
    def __init__(self, *args, **kwargs):

        # initialize Tkinter
        tk.Tk.__init__(self, *args, **kwargs)

        # hide main window
        self.wm_withdraw()

        # show "please wait..." window
        self.wait = tk.Toplevel(self)
        label = tk.Label(self.wait, text="Please wait...")
        label.pack()

        # schedule the rest of the initialization to happen
        # after the event loop has started
        self.after(100, self.init_phase_2)

    def init_phase_2(self):

        # simulate doing something...
        time.sleep(10)

        # we're done. Close the wait window, show the main window
        self.wait.destroy()
        self.wm_deiconify()

app = SampleApp()
app.mainloop()

撰写回答