kull3rk3ks
kull3rk3ks

Reputation: 3

Cyclic label update in Python

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"

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

Upvotes: 0

Views: 720

Answers (1)

elya5
elya5

Reputation: 2258

You can use gobject.timeout_add (see the documentation here).

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).

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()

Upvotes: 2

Related Questions