views:

190

answers:

1

I am trying to develop a GNOME applet (put into panel) using python (pyGTK). I've started by following the tutorial suggested in other SO question.

My plan is to let the applet do something in the background in a repetitive fashion (causing its display to be updated). So I thought I am gonna need threads to do it. I've seen several tutorials on how to use threads with pyGTK - most of them follow the pyGTK FAQ. And all of them suggest being cautious.

I tried with the different versions, incl.

#!/usr/bin/python

import pygtk
import sys
pygtk.require('2.0')
import gtk
import gobject
gobject.threads_init()

import gnomeapplet
import time
from threading import Thread

def threadFunction(label):
    gobject.idle_add(label.set_text, 'In the thread')

def factory(applet, iid):
        text = gtk.Label('Start %s' % iid)
        applet.add(text)
        applet.show_all()
        Thread(target=threadFunction, args=(text)).start()
        return True

if __name__ == '__main__':
        print "Starting factory"
        gnomeapplet.bonobo_factory("OAFIID:Gnome_Panel_Example_Factory", gnomeapplet.Applet.__gtype__, "Simple gnome applet example", "1.0", factory)

But it doesn't work. The thread execution seems to hang when trying to update the presentation (gobject.idle_add). I tried:

  • replacing gobject.threads_init() with gtk.gdk.threads_init() - because this is what some of the tutorials use,
  • subclassing threading.Thread class instead of using Thread(target=)
  • using gtk.threads_enter and gtk.threads_leave around any code that is run within a separate thread and updates the widgets,

What is my mistake then?

Is threading imcompatible with applets (as opposed to other pyGTK programs)?

+1  A: 

According to several comments on the gtk lists, you shouldn't be trying to update your user interface from threads. It would be better to poll the child threads from your main application. For references see here and here. More can be found by searching the archives. I don't know of any official documentation of this.

Matthew Talbert
But isn't `gobject.idle_add` supposed to call the update from within the main thread? At least this is what it seems it was invented for? Thanks for your answer anyway.
Grzegorz Oledzki
I don't think it will do it from within the main thread if you're calling it from another. The intention of idle_add is to allow gobject to call that function when it has no higher priority things to do. At this point, I'm venturing into speculation however. My advice is still to poll your worker thread from the main thread and call idle_add from the main thread.
Matthew Talbert
btw, including the gtk tag might make your question more visible to people who know more about gtk internals.
Matthew Talbert
Grzegorz Oledzki
about "gtk" tag: added this one. Thanks!
Grzegorz Oledzki
I agree, the docs certainly make it seem as if using idle_add is the appropriate way to accomplish this.
Matthew Talbert