def init(self, msecs=1000): # default = 1 second
Frame.init(self)
self.msecs = msecs
self.pack()
stopper = Button(self, text='Stop the beeps!', command=self.quit)
stopper.pack()
stopper.config(bg='navy', fg='white', bd=8)
self.stopper = stopper
self.repeater()
def repeater(self): # on every N millisecs
self.bell() # beep now
self.stopper.flash() # flash button now
self.after(self.msecs, self.repeater) # reschedule handler
if name == 'main': Alarm(msecs=1000).mainloop()
This script builds the window in Figure 9-41 and periodically calls both the button
widget’s flash method to make the button flash momentarily (it alternates colors
quickly) and the tkinter bell method to call your system’s sound interface. The
repeater method beeps and flashes once and schedules a callback to be invoked after
a specific amount of time with the after method.
Figure 9-41. Stop the beeps!
But after doesn’t pause the caller: callbacks are scheduled to occur in the background,
while the program performs other processing—technically, as soon as the Tk event
loop is able to notice the time rollover. To make this work, repeater calls after each
time through, to reschedule the callback. Delayed events are one-shot callbacks; to
repeat the event as a loop, we need to reschedule it anew.
The net effect is that when this script runs, it starts beeping and flashing once its one-
button window pops up. And it keeps beeping and flashing. And beeping. And flashing.
Other activities and GUI operations don’t affect it. Even if the window is iconified, the
beeping continues, because tkinter timer events fire in the background. You need to
kill the window or press the button to stop the alarm. By changing the msecs delay, you
can make this beep as fast or as slow as your system allows (some platforms can’t beep
as fast as others...). This may or may not be the best demo to launch in a crowded office,
but at least you’ve been warned.
586 | Chapter 9: A tkinter Tour, Part 2