Hi, I am using pygtk for the first times.
I am wondering what would be the best "pattern" to interface pygtk with a thread. The thread is collecting informations (over the network for example) or is doing some long calculations. I would like also to separate the gui part to the action part so that I should be easier to maintain. ************************************************************ What should be the best practice in order to achieve this ? *********************************************************** What I use now is : 1) the gui is launching the "action" evrey 1 sec and is checking for message using a queue every second also. gui.py ....etc ... class window1(SimpleGladeApp): [EMAIL PROTECTED] class window1 } [EMAIL PROTECTED] init window1.__init__ { def __init__(self, path='gui.glade', root='window1', domain=app_name, kwargs={}): path = os.path.join(glade_dir, path) SimpleGladeApp.__init__(self, path, root, domain, **kwargs) self.q=Queue.Queue() self.action=act.action(self.q) gobject.timeout_add (1000,self.action.go) # this is the action asked gobject.timeout_add (1000,self.process) # check if a new message is available in the queue def process (self): dir (self.q) if self.q.empty() == False : print "from main ",self.q.get() return True ...etc .... 2) The action part is making somehow the interface between the running thread and the gui : It puts the new information in the queue for the gui to process it later. action.py import os import gui import time import Queue import Spethread # thread that always run in the background class Singleton(object): _instance = None def __new__(cls, *args, **kwargs): if not cls._instance: cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs) return cls._instance class action(Singleton): def __init__(self, queue): self.q=queue self.thread_seb=Spethread.worker() self.thread_seb.start() self.go() def go(self): if self.thread_seb: reponse=self.thread_seb.status() self.q.put(reponse) else : self.q.put("le thread n'existe plus ") return True def stop(self): self.thread_seb.die() 3) The thread part is "just" a thread that should from time to time time.Sleep in order for action to query if it has some new messages. Spethread.py import threading import time class worker(threading.Thread): def __init__(self): threading.Thread.__init__(self) self.value=0 self.go_on=1 def run(self): print "self.go_on=",self.go_on while self.go_on == 1: self.value=int(time.time()) res=2 for i in range(0, 100): res=res^i print res time.Sleep(0.01) def status(self): return self.value def die(self): print "die request" self.go_on=0 Thanks in advance for sharing this informations. Sebastien. PS : the entire gui.py [EMAIL PROTECTED] python gui.py { [EMAIL PROTECTED] header gui.py { #!/usr/bin/env python # -*- coding: UTF8 -*- # Python module gui.py # Autogenerated from gui.glade # Generated on Wed Sep 20 22:03:00 2006 # Warning: Do not modify any context comment beginning with # @-- # They are required to keep user's code # Doing so will make it unable for kefir to help you further manage your project [EMAIL PROTECTED] header gui.py } [EMAIL PROTECTED] app gui { import os import gobject import gtk import action as act import Queue from SimpleGladeApp import SimpleGladeApp, bindtextdomain app_name = 'gui' app_version = '0.0.1' glade_dir = '' locale_dir = '' bindtextdomain(app_name, locale_dir) [EMAIL PROTECTED] app gui } [EMAIL PROTECTED] window window1 { [EMAIL PROTECTED] class window1 { class window1(SimpleGladeApp): [EMAIL PROTECTED] class window1 } [EMAIL PROTECTED] init window1.__init__ { def __init__(self, path='gui.glade', root='window1', domain=app_name, kwargs={}): path = os.path.join(glade_dir, path) SimpleGladeApp.__init__(self, path, root, domain, **kwargs) self.q=Queue.Queue() self.action=act.action(self.q) gobject.timeout_add (1000,self.action.go) gobject.timeout_add (1000,self.process) [EMAIL PROTECTED] init window1.__init__ } [EMAIL PROTECTED] new window1.new { def new(self): print 'A new %s has been created' % self.__class__.__name__ [EMAIL PROTECTED] new window1.new } [EMAIL PROTECTED] custom window1 { # Write your own methods here [EMAIL PROTECTED] custom window1 } [EMAIL PROTECTED] callback window1.on_button1_clicked { def on_button1_clicked(self, widget, args=[]): print 'on_button1_clicked called with self.%s' % widget.get_name() self.action.stop() print "arrete de thread" [EMAIL PROTECTED] callback window1.on_button1_clicked } def process (self): dir (self.q) if self.q.empty() == False : print "from main ",self.q.get() return True [EMAIL PROTECTED] window window1 } [EMAIL PROTECTED] main gui.py { [EMAIL PROTECTED] init main { def main(): [EMAIL PROTECTED] init main } [EMAIL PROTECTED] body main { Window1 = window1() Window1.run() [EMAIL PROTECTED] body main } [EMAIL PROTECTED] main gui.py } [EMAIL PROTECTED] run gui.py { if __name__ == '__main__': main() [EMAIL PROTECTED] run gui.py } [EMAIL PROTECTED] python gui.py } the glade file: <?xml version="1.0" standalone="no"?> <!--*- mode: xml -*--> <!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd"> <glade-interface> <widget class="GtkWindow" id="window1"> <property name="visible">True</property> <property name="title" translatable="yes">window1</property> <property name="type">GTK_WINDOW_TOPLEVEL</property> <property name="window_position">GTK_WIN_POS_NONE</property> <property name="modal">False</property> <property name="resizable">True</property> <property name="destroy_with_parent">False</property> <property name="decorated">True</property> <property name="skip_taskbar_hint">False</property> <property name="skip_pager_hint">False</property> <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property> <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> <property name="focus_on_map">True</property> <property name="urgency_hint">False</property> <child> <widget class="GtkVBox" id="vbox1"> <property name="visible">True</property> <property name="homogeneous">False</property> <property name="spacing">0</property> <child> <widget class="GtkEntry" id="entry1"> <property name="visible">True</property> <property name="can_focus">True</property> <property name="editable">True</property> <property name="visibility">True</property> <property name="max_length">0</property> <property name="text" translatable="yes">this is it</property> <property name="has_frame">True</property> <property name="invisible_char">*</property> <property name="activates_default">False</property> </widget> <packing> <property name="padding">0</property> <property name="expand">True</property> <property name="fill">True</property> </packing> </child> <child> <widget class="GtkButton" id="button1"> <property name="visible">True</property> <property name="can_focus">True</property> <property name="label" translatable="yes">button1</property> <property name="use_underline">True</property> <property name="relief">GTK_RELIEF_NORMAL</property> <property name="focus_on_click">True</property> <signal name="clicked" handler="on_button1_clicked" last_modification_time="Wed, 20 Sep 2006 19:59:06 GMT"/> </widget> <packing> <property name="padding">0</property> <property name="expand">False</property> <property name="fill">False</property> <property name="pack_type">GTK_PACK_END</property> </packing> </child> </widget> </child> </widget> </glade-interface> -- http://mail.python.org/mailman/listinfo/python-list