PyGTK: Stopwatch [update]

Posted on 8 December 2009 - 22:31 in Programming - Comments (1)

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:
pygtk-stopwatch

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 »

  1. #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.


RSS Comments - TrackBack URL

Leave a comment

This work is licensed under a Creative Commons Attribution 2.5 Switzerland License
Powered by WordPress