# compute the angles in radians of the hands of the clock
now = datetime.datetime.now()
hours = now.hour * math.pi / 6
minutes = now.minute * math.pi / 30
seconds = now.second * math.pi / 30
context.set_line_cap(cairo.LINE_CAP_ROUND)
# draw the hours hand
context.save()
context.set_source_rgba(0.337, 0.612, 0.117, 0.9) # green
context.set_line_width(7)
context.move_to(x, y)
context.line_to(x + math.sin(hours + minutes/12) * (radius * 0.5),
y - math.cos(hours + minutes/12) * (radius * 0.5))
context.stroke()
context.restore()
# draw the minutes hand
context.save()
context.set_source_rgba(0.117, 0.337, 0.612, 0.9) # blue
context.set_line_width(5)
context.move_to(x, y)
context.line_to(x + math.sin(minutes + seconds/60) * (radius * 0.8),
y - math.cos(minutes + seconds/60) * (radius * 0.8))
context.stroke()
context.restore()
# draw the seconds hand
context.save()
context.set_source_rgba(0.7, 0.7, 0.7, 0.8) # gray
context.set_line_width(3)
context.move_to(x, y)
context.line_to(x + math.sin(seconds) * (radius * 0.9),
y - math.cos(seconds) * (radius * 0.9))
context.stroke()
context.restore()
At this point the clock hands are not moving yet. We need a timer to move the clock hands every second. I need some extra help to translate the gtkmm timer code to PyGTK, and this tutorial just did that. What it does is to set up a timer in __init__():
gobject.timeout_add_seconds(1, self.on_timeout)
to invalidate the clock face every second:
def on_timeout(self):
win = self.get_window()
rect = self.get_allocation()
win.invalidate_rect(rect, False)
return True
Now we have an analog clock written in PyGTK. Here is the complete source code:
import datetime
import gobject
import gtk
import math
class ClockFace(gtk.DrawingArea):
def __init__(self):
gtk.DrawingArea.__init__(self)
self.connect("expose_event", self.expose)
gobject.timeout_add_seconds(1, self.on_timeout)
def expose(self, widget, event):
self.context = widget.window.cairo_create()
self.context.rectangle(event.area.x, event.area.y,
event.area.width, event.area.height)
self.context.clip()
self.draw(self.context)
return False
def on_timeout(self):
win = self.get_window()
rect = self.get_allocation()
win.invalidate_rect(rect, False)
return True
def draw(self, context):
rect = self.get_allocation()
x = rect.x + rect.width / 2
y = rect.y + rect.height / 2
radius = min(rect.width / 2, rect.height / 2) - 5
# clock background
context.arc(x, y, radius, 0, 2 * math.pi)
context.set_source_rgb(1, 1, 1)
context.fill_preserve()
context.set_source_rgb(0, 0, 0)
context.stroke()
# clock ticks
for i in range(12):
context.save()
if i % 3 == 0:
inset = 0.2 * radius
else:
inset = 0.1 * radius
context.set_line_width(0.5 * context.get_line_width())
context.move_to(x + (radius-inset) * math.cos(i * math.pi/6),
y + (radius-inset) * math.sin(i * math.pi/6))
context.line_to(x + radius * math.cos(i * math.pi/6),
y + radius * math.sin(i * math.pi/6))
context.stroke()
context.restore()
# compute the angles in radians of the hands of the clock
now = datetime.datetime.now()
hours = now.hour * math.pi / 6
minutes = now.minute * math.pi / 30
seconds = now.second * math.pi / 30
context.set_line_cap(cairo.LINE_CAP_ROUND)
# draw the hours hand
context.save()
context.set_source_rgba(0.337, 0.612, 0.117, 0.9) # green
context.set_line_width(7)
context.move_to(x, y)
context.line_to(x + math.sin(hours + minutes/12) * (radius * 0.5),
y - math.cos(hours + minutes/12) * (radius * 0.5))
context.stroke()
context.restore()
# draw the minutes hand
context.save()
context.set_source_rgba(0.117, 0.337, 0.612, 0.9) # blue
context.set_line_width(5)
context.move_to(x, y)
context.line_to(x + math.sin(minutes + seconds/60) * (radius * 0.8),
y - math.cos(minutes + seconds/60) * (radius * 0.8))
context.stroke()
context.restore()
# draw the seconds hand
context.save()
context.set_source_rgba(0.7, 0.7, 0.7, 0.8) # gray
context.set_line_width(3)
context.move_to(x, y)
context.line_to(x + math.sin(seconds) * (radius * 0.9),
y - math.cos(seconds) * (radius * 0.9))
context.stroke()
context.restore()
def main():
window = gtk.Window()
clock = ClockFace()
window.add(clock)
window.connect("destroy", gtk.main_quit)
window.show_all()
gtk.main()
if __name__ == '__main__':
main()
1 comment:
great work!!
Post a Comment