Cyclic label update in Python
Question: I'm trying to get dynamic cyclic (every half a second) label updates from a
Webservice in Python where I parse a JSON string and return its contents to
the GUI (made with Glade 3.8.1).

I have started from a basic example and the code I've written so far looks
like this:

    
    
    import sys
    import json
    import urllib2
    import time
    
    try:
        import pygtk
        pygtk.require("2.0")
    except:
        pass
    try:
        import gtk.glade
        import gtk
    except:
        sys.exit(1)
    
    class cRioHMI():
    
        def on_MainWindow_destroy(self, data = None):
            print "quit with cancel"
            gtk.main_quit()
    
        def on_gtk_quit_activate(self, data = None):
            print "quit from menu"
            gtk.main_quit()
    
        def on_btnTest_clicked(self, widget):
            print "Button Pressed"
    
        def on_gtk_about_activate(self, data = None):
            print "About Page Accessed"
            self.response = self.about.run()
            self.about.hide()
    
        def __init__(self):
    
            self.gladefile = "Assets/HMI.glade"
            self.builder = gtk.Builder()
            self.builder.add_from_file(self.gladefile)
            self.builder.connect_signals(self)
            self.window = self.builder.get_object("MainWindow")
            self.about = self.builder.get_object("AboutDialogue")
            self.templable = self.builder.get_object("lbl_Temperature")
            self.window.show()
    
        def update_Values(self, data = None):
            response = urllib2.urlopen('http://10.10.10.11:8001/WebUI/Temperatures/GetTemperatures')
            data = json.load(response)
            temperature = data['Temperature2'][1]
            self.templable.set_text(str(temperature))
            time.sleep(.5)
    
    
    
    
    if __name__ == "__main__":
        HMI = cRioHMI()
        gtk.main()
    

When I use the code from the update_Values method on a click event, the code
performs as expected

    
    
        def on_btnTest_clicked(self, widget):
        response = urllib2.urlopen('http://10.10.10.11:8001/WebUI/Temperatures/GetTemperatures')
        data = json.load(response)
        temperature = data['Temperature2'][1]
        self.templable.set_text(str(temperature))
        time.sleep(.5)
        print "Button Pressed"
    

  * but I would like to update multiple labels in a cyclic manner and still have event driven actions.

What is the best way to do that? Please note, that I'm new to python.


Answer: You can use `gobject.timeout_add` (see the documentation
[here](http://www.pygtk.org/pygtk2reference/gobject-functions.html#function-
gobject--timeout-add)).

So in your `__init__` you would have something like `gobject.timeout_add(1000,
self.updateValues)`. If you return False the timeout will not be called again.

You should also not use `time.sleep`. This is a blocking call. That means your
GUI will freeze as it cannot handle incoming events. The same thing will
happen with the `urllib2.urlopen` call, if it takes too much time. To prevent
this you can run updateValues in a separate Thread. Then you would have to use
`gobject.idle_add` to set the text of the label (see
[documentation](http://www.pygtk.org/pygtk2reference/gobject-
functions.html#function-gobject--idle-add)).

Here is a small example. It is just a counter (and would not need threading)
but I marked the place where your urllib2.urlopen would go with a comment:

    
    
    #!/usr/bin/env python2
    
    from threading import Thread
    from pygtk import gtk, gobject
    
    class Window(gtk.Window):
        def __init__(self):
            gtk.Window.__init__(self)
            self.connect('delete-event', gtk.main_quit)
            self.label = gtk.Label('1')
            self.add(self.label)
            gobject.timeout_add_seconds(1, self.threaded)
    
        def threaded(self):
            thread = Thread(target=self.updateValues)
            thread.start()
            return True
    
        def updateValues(self):
            # urllib.urlopen calls
            n = int(self.label.get_text())
            gobject.idle_add(self.label.set_text, str(n + 1))
    
    win = Window()
    win.show_all()
    gobject.threads_init()
    gtk.main()
    

