Recipe11.8.Implementing a Stopwatch in Tkinter


Recipe 11.8. Implementing a Stopwatch in Tkinter

Credit: JØrgen Cederberg, Tobias Klausmann

Problem

You are coding an application in Tkinter and need a widget that implements a stopwatch.

Solution

Implementing a new widget is almost always best done by subclassing Frame:

from Tkinter import * import time class StopWatch(Frame):     """ Implements a stop watch frame widget. """     msec = 50     def _ _init_ _(self, parent=None, **kw):         Frame._ _init_ _(self, parent, kw)         self._start = 0.0         self._elapsedtime = 0.0         self._running = False         self.timestr = StringVar( )         self.makeWidgets( )     def makeWidgets(self):         """ Make the time label. """         l = Label(self, textvariable=self.timestr)         self._setTime(self._elapsedtime)         l.pack(fill=X, expand=NO, pady=2, padx=2)     def _update(self):         """ Update the label with elapsed time. """         self._elapsedtime = time.time( ) - self._start         self._setTime(self._elapsedtime)         self._timer = self.after(self.msec, self._update)     def _setTime(self, elap):         """ Set the time string to Minutes:Seconds:Hundredths """         minutes = int(elap/60)         seconds = int(elap - minutes*60.0)         hseconds = int((elap - minutes*60.0 - seconds)*100)         self.timestr.set('%02d:%02d:%02d' % (minutes, seconds, hseconds))     def Start(self):         """ Start the stopwatch, ignore if already running. """         if not self._running:             self._start = time.time( ) - self._elapsedtime             self._update( )             self._running = True     def Stop(self):         """ Stop the stopwatch, ignore if already stopped. """         if self._running:             self.after_cancel(self._timer)             self._elapsedtime = time.time( ) - self._start             self._setTime(self._elapsedtime)             self._running = False     def Reset(self):         """ Reset the stopwatch. """         self._start = time.time( )         self._elapsedtime = 0.0         self._setTime(self._elapsedtime)

Discussion

Here is an example of use of this StopWatch widget, presented, as usual, with a guard of if _ _name_ _ == '_ _main_ _' so we can make it part of the module containing the class and have it run when the module is executed as a "main script":

if _ _name_ _ == '_ _main_ _':     def main( ):         root = Tk( )         sw = StopWatch(root)         sw.pack(side=TOP)         Button(root, text='Start', command=sw.Start).pack(side=LEFT)         Button(root, text='Stop', command=sw.Stop).pack(side=LEFT)         Button(root, text='Reset', command=sw.Reset).pack(side=LEFT)         Button(root, text='Quit', command=root.quit).pack(side=LEFT)         root.mainloop( )     main( )

You might want to use time.clock instead of time.time if your stopwatch's purpose is to measure the amount of CPU time that your program is taking, rather than the amount of elapsed time. I used time.time, without even bothering to make that choice easily customizable (you'll need to edit its several appearances in the recipe's code), because it seems the most natural choice to me by far. One aspect that you can customize easily, by subclassing and data overriding or simply by setting the msec instance attribute on a particular StopWatch instance, is how often the time display is updated onscreen; the default of 50 milliseconds, which translates to 20 updates a second, may well mean updates that are too frequent for your purposes, although they suit my own just fine.

See Also

Docs about the time module in the Library Reference and Python in a Nutshell; information about Tkinter can be obtained from a variety of sources, such as Fredrik Lundh, An Introduction to Tkinter (PythonWare: http://www.pythonware.com/library), New Mexico Tech's Tkinter Reference (http://www.nmt.edu/tcc/help/lang/python/docs.html), Python in a Nutshell, and various other books.



Python Cookbook
Python Cookbook
ISBN: 0596007973
EAN: 2147483647
Year: 2004
Pages: 420

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net