To understand how these points are mapped to a canvas, you first need to know that
the width and height of a circle are always the same—the radius × 2. Because tkinter
canvas (X,Y) coordinates start at (0,0) in the upper-left corner, the plotter GUI must
offset the circle’s center point to coordinates (width/2, width/2)—the origin point from
which lines are drawn. For instance, in a 400 × 400 circle, the canvas center is (200,200).
A line to the 90-degree angle point on the right side of the circle runs from (200,200)
to (400,200)—the result of adding the (200,0) point coordinates plotted for the radius
and angle. A line to the bottom at 180 degrees runs from (200,200) to (200,400) after
factoring in the (0,-200) point plotted.
This point-plotting algorithm used by plotterGui, along with a few scaling constants,
is at the heart of the PyClock analog display. If this still seems a bit much, I suggest you
focus on the PyClock script’s digital display implementation first; the analog geometry
plots are really just extensions of underlying timing mechanisms used for both display
modes. In fact, the clock itself is structured as a generic Frame object that embeds digital
and analog display objects and dispatches time change and resize events to both in the
same way. The analog display is an attached Canvas that knows how to draw circles,
but the digital object is simply an attached Frame with labels to show time components.
Running PyClock
Apart from the circle geometry bit, the rest of PyClock is straightforward. It simply
draws a clock face to represent the current time and uses widget after methods to wake
itself up 10 times per second to check whether the system time has rolled over to the
next second. On second rollovers, the analog second, minute, and hour hands are re-
drawn to reflect the new time (or the text of the digital display’s labels is changed). In
terms of GUI construction, the analog display is etched out on a canvas, redrawn
whenever the window is resized, and changes to a digital format upon request.
PyClock also puts Python’s standard time module into service to fetch and convert
system time information as needed for a clock. In brief, the onTimer method gets system
time with time.time, a built-in tool that returns a floating-point number giving seconds
since the epoch—the point from which your computer counts time. The time.local
time call is then used to convert epoch time into a tuple that contains hour, minute,
and second values; see the script and Python library manual for additional details.
Checking the system time 10 times per second may seem intense, but it guarantees that
the second hand ticks when it should, without jerks or skips (after events aren’t pre-
cisely timed). It is not a significant CPU drain on systems I use. On Linux and Windows,
PyClock uses negligible processor resources—what it does use is spent largely on screen
updates in analog display mode, not on after events.§
§The PyDemos script of the preceding chapter, for instance, launches seven clocks that run in the same process,
and all update smoothly on my (relatively slow) Windows 7 netbook laptop. They together consume a low
single-digit percentage of the CPU’s bandwidth, and often less than the Task Manager.
PyClock: An Analog/Digital Clock Widget | 751