PyGTK: Stopwatch [update]
I was looking for a little easy-to-use stopwatch for gnome without success.
Well then, let’s make an own one.
Looks like this after 13 minutes, 37 seconds and 70 miliseconds:

Magic by: python, pygtk, gobject
Code below or here
Update 1
Joakim Gebart increased the accuracy by using time.time().
See the comment for a patch.
#!/usr/bin/env python # -*- coding: utf-8 -*- # # Nifty GTK stopwatch using pygtk and gobject. # min:sec.msec display; start, stop, reset and quit buttons. # # Version: 1.0 # Requires: python >=2.5, python-gtk2, python-gobject # # Copyright (C) 2009 wag@wag-net.ch # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. import pygtk, gtk, pango pygtk.require('2.0') import gobject gobject.threads_init() class W_Timer(): def __init__(self): self.s = 0.0 self.m = 0 self.g_id = 0 self.win() def b_start_cb(self, widget): # Start gobject, impossible to speed up by clicking multiple times if self.g_id == 0: self.g_id = gobject.timeout_add(100, self.count) def b_stop_cb(self, widget): # Kill gobject, reset g_id if self.g_id != 0: gobject.source_remove(self.g_id) self.g_id = 0 def b_reset_cb(self, widget): # Reset time self.s = 0.0 self.m = 0 self.l_time.set_text("00:00.0") def win(self): win = gtk.Window(gtk.WINDOW_TOPLEVEL) win.connect("destroy", lambda q: gtk.main_quit()) win.set_title("Stopwatch") win.set_border_width(20) # Table and window size table = gtk.Table(2, 3, False) win.set_geometry_hints(table, min_width=160, min_height=150) table.set_row_spacings(5) table.set_col_spacings(3) win.add(table) # AspectFrame, into table af_time = gtk.AspectFrame() table.attach(af_time, 0, 2, 0, 1) # Time label, into aspect frame, font size: 19 self.l_time = gtk.Label("00:00.0") self.l_time.modify_font(pango.FontDescription("19")) self.l_time.set_padding(10, 5) af_time.add(self.l_time) # Buttons, into table, font size: 11 b_start = gtk.Button("Start") b_start.child.modify_font(pango.FontDescription("11")) table.attach(b_start, 0, 1, 1, 2) b_start.connect("clicked", self.b_start_cb) b_stop = gtk.Button("Stop") b_stop.child.modify_font(pango.FontDescription("11")) table.attach(b_stop, 1, 2, 1, 2) b_stop.connect("clicked", self.b_stop_cb) b_reset = gtk.Button("Reset") b_reset.child.modify_font(pango.FontDescription("11")) table.attach(b_reset, 0, 1, 2, 3) b_reset.connect("clicked", self.b_reset_cb) b_quit = gtk.Button(" Quit ") b_quit.child.modify_font(pango.FontDescription("11")) table.attach(b_quit, 1, 2, 2, 3) b_quit.connect("clicked", lambda q: gtk.main_quit()) # Run GTK and show window, buttons, etc. win.show_all() gtk.main() def count(self): # A minute yet? if self.s > 60: self.m += 1 self.s = 0.0 else: self.s += 0.1 # Set new time to label self.l_time.set_text("%02i:%04.1f" % (self.m , self.s)) # Play it again, Sam return True if __name__ == "__main__": t = W_Timer()
#1 — Comment by Joakim Gebart — 21 July 2010 - 08:09
I improved the accuracy a bit by using time.time() instead of adding to a counter.
Full source: http://gebart.pastebin.com/AiMBafkD
A patch is included below:
— pygtk-stopwatch.py.orig 2010-07-21 08:48:35.931061650 +0200
+++ pygtk-stopwatch.py 2010-07-21 08:50:36.522047750 +0200
@@ -24,6 +24,7 @@
import pygtk, gtk, pango
+import time
pygtk.require(’2.0′)
import gobject
gobject.threads_init()
@@ -39,7 +40,9 @@
def b_start_cb(self, widget):
# Start gobject, impossible to speed up by clicking multiple times
if self.g_id == 0:
- self.g_id = gobject.timeout_add(100, self.count)
+ # setting the timeout to 1 ms is too fast on my machine.
+ self.g_id = gobject.timeout_add(10, self.count)
+ self.starttime = time.time()
def b_stop_cb(self, widget):
# Kill gobject, reset g_id
@@ -49,9 +52,10 @@
def b_reset_cb(self, widget):
# Reset time
+ self.starttime = time.time()
self.s = 0.0
self.m = 0
- self.l_time.set_text(“00:00.0″)
+ self.l_time.set_text(“00:00.000″)
def win(self):
win = gtk.Window(gtk.WINDOW_TOPLEVEL)
@@ -71,7 +75,7 @@
table.attach(af_time, 0, 2, 0, 1)
# Time label, into aspect frame, font size: 19
- self.l_time = gtk.Label(“00:00.0″)
+ self.l_time = gtk.Label(“00:00.000″)
self.l_time.modify_font(pango.FontDescription(“19″))
self.l_time.set_padding(10, 5)
af_time.add(self.l_time)
@@ -102,15 +106,12 @@
gtk.main()
def count(self):
- # A minute yet?
- if self.s > 60:
- self.m += 1
- self.s = 0.0
- else:
- self.s += 0.1
+ # Split time into minutes and seconds
+ timediff = time.time() – self.starttime
+ (self.m, self.s) = divmod(timediff, 60.0)
# Set new time to label
- self.l_time.set_text(“%02i:%04.1f” % (self.m , self.s))
+ self.l_time.set_text(“%02i:%06.3f” % (self.m , self.s))
# Play it again, Sam
return True
-
Hi, thanks for your contribution Joakim.
Very elegant timing mechanism.