Tkinter: one or more mainloops?
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.
精彩评论