开发者

Tkinter: one or more mainloops?

开发者 https://www.devze.com 2023-04-06 22:35 出处:网络
I have an already large Tkinter program, so that I have an init file, where the root = Tk() window is defined (containing basically a Text widget and a few other things), some more code, and last the

I have an already large Tkinter program, so that I have an init file, where the root = Tk() window is defined (containing basically a Text widget and a few other things), some more code, and last the call to mainloop() function.

Everything works, until I needed to call a procedure before the mainloop, and I wanted to raise a wait window at the begin, to be destroyed at procedure's end.

I wrote something like:

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

But it doesn't and cannot work, since mainloop() has not been called yet!

If I instead do:

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

The program stops at this first mainloop, d开发者_开发问答oesn't finish the procedure call.

mainloop() should be used as your last program line, after which the Tkinter program works by a logic driven by user clicks and interactions, etc.

Here, I need a sequence of raise window > do stuff > destroy window > mainloop


You are correct that mainloop needs to be called once, after your program has initialized. This is necessary to start the event loop, which is necessary for windows to draw themselves, respond to events, and so on.

What you can do is break your initialization into two parts. The first -- creating the wait window -- happens prior to starting the event loop. The second -- doing the rest of the initialization -- happens once the event loop has started. You can do this by scheduling the second phase via the after method.

Here's a simple example:

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()


You should use Tkinter's method to run asyncore's loop function, but you should use asyncore.poll(0) instead of asyncore.loop(). If you call function asyncore.poll(0) every x ms, it has no longer an effect on Tkinter's main loop.

0

精彩评论

暂无评论...
验证码 换一张
取 消