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(SimpleG ladeApp):
#@-- class window1 }
#@-- init window1.__init_ _ {
def __init__(self, path='gui.glade ',
root='window1',
domain=app_name , kwargs={}):
path = os.path.join(gl ade_dir, path)
SimpleGladeApp. __init__(self, path, root, domain, **kwargs)
self.q=Queue.Qu eue()
self.action=act .action(self.q)
gobject.timeout _add (1000,self.acti on.go) # this is the action
asked
gobject.timeout _add (1000,self.proc ess) # 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.ge t()
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(objec t):
_instance = None
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super(Singleton , cls).__new__(cl s, *args,
**kwargs)
return cls._instance
class action(Singleto n):
def __init__(self, queue):
self.q=queue
self.thread_seb =Spethread.work er()
self.thread_seb .start()
self.go()
def go(self):
if self.thread_seb :
reponse=self.th read_seb.status ()
self.q.put(repo nse)
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(threadin g.Thread):
def __init__(self):
threading.Threa d.__init__(self )
self.value=0
self.go_on=1
def run(self):
print "self.go_on=",s elf.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
gH#@-- python gui.py {
#@-- 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
#@-- header gui.py }
#@-- 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)
#@-- app gui }
#@-- window window1 {
#@-- class window1 {
class window1(SimpleG ladeApp):
#@-- class window1 }
#@-- init window1.__init_ _ {
def __init__(self, path='gui.glade ',
root='window1',
domain=app_name , kwargs={}):
path = os.path.join(gl ade_dir, path)
SimpleGladeApp. __init__(self, path, root, domain, **kwargs)
self.q=Queue.Qu eue()
self.action=act .action(self.q)
gobject.timeout _add (1000,self.acti on.go)
gobject.timeout _add (1000,self.proc ess)
#@-- init window1.__init_ _ }
#@-- new window1.new {
def new(self):
print 'A new %s has been created' % self.__class__. __name__
#@-- new window1.new }
#@-- custom window1 {
# Write your own methods here
#@-- custom window1 }
#@-- callback window1.on_butt on1_clicked {
def on_button1_clic ked(self, widget, args=[]):
print 'on_button1_cli cked called with self.%s' %
widget.get_name ()
self.action.sto p()
print "arrete de thread"
#@-- callback window1.on_butt on1_clicked }
def process (self):
dir (self.q)
if self.q.empty() == False :
print "from main ",self.q.ge t()
return True
#@-- window window1 }
#@-- main gui.py {
#@-- init main {
def main():
#@-- init main }
#@-- body main {
Window1 = window1()
Window1.run()
#@-- body main }
#@-- main gui.py }
#@-- run gui.py {
if __name__ == '__main__':
main()
#@-- run gui.py }
#@-- 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="GtkWindo w" id="window1">
<property name="visible"> True</property>
<property name="title" translatable="y es">window1</property>
<property name="type">GTK _WINDOW_TOPLEVE L</property>
<property name="window_po sition">GTK_WIN _POS_NONE</property>
<property name="modal">Fa lse</property>
<property name="resizable ">True</property>
<property name="destroy_w ith_parent">Fal se</property>
<property name="decorated ">True</property>
<property name="skip_task bar_hint">False </property>
<property name="skip_page r_hint">False</property>
<property name="type_hint ">GDK_WINDOW_TY PE_HINT_NORMAL</property>
<property name="gravity"> GDK_GRAVITY_NOR TH_WEST</property>
<property name="focus_on_ map">True</property>
<property name="urgency_h int">False</property>
<child>
<widget class="GtkVBox" id="vbox1">
<property name="visible"> True</property>
<property name="homogeneo us">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="visibilit y">True</property>
<property name="max_lengt h">0</property>
<property name="text" translatable="y es">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">T rue</property>
<property name="fill">Tru e</property>
</packing>
</child>
<child>
<widget class="GtkButto n" id="button1">
<property name="visible"> True</property>
<property name="can_focus ">True</property>
<property name="label" translatable="y es">button1</property>
<property name="use_under line">True</property>
<property name="relief">G TK_RELIEF_NORMA L</property>
<property name="focus_on_ click">True</property>
<signal name="clicked" handler="on_but ton1_clicked"
last_modificati on_time="Wed, 20 Sep 2006 19:59:06 GMT"/>
</widget>
<packing>
<property name="padding"> 0</property>
<property name="expand">F alse</property>
<property name="fill">Fal se</property>
<property name="pack_type ">GTK_PACK_ END</property>
</packing>
</child>
</widget>
</child>
</widget>
</glade-interface>
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(SimpleG ladeApp):
#@-- class window1 }
#@-- init window1.__init_ _ {
def __init__(self, path='gui.glade ',
root='window1',
domain=app_name , kwargs={}):
path = os.path.join(gl ade_dir, path)
SimpleGladeApp. __init__(self, path, root, domain, **kwargs)
self.q=Queue.Qu eue()
self.action=act .action(self.q)
gobject.timeout _add (1000,self.acti on.go) # this is the action
asked
gobject.timeout _add (1000,self.proc ess) # 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.ge t()
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(objec t):
_instance = None
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super(Singleton , cls).__new__(cl s, *args,
**kwargs)
return cls._instance
class action(Singleto n):
def __init__(self, queue):
self.q=queue
self.thread_seb =Spethread.work er()
self.thread_seb .start()
self.go()
def go(self):
if self.thread_seb :
reponse=self.th read_seb.status ()
self.q.put(repo nse)
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(threadin g.Thread):
def __init__(self):
threading.Threa d.__init__(self )
self.value=0
self.go_on=1
def run(self):
print "self.go_on=",s elf.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
gH#@-- python gui.py {
#@-- 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
#@-- header gui.py }
#@-- 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)
#@-- app gui }
#@-- window window1 {
#@-- class window1 {
class window1(SimpleG ladeApp):
#@-- class window1 }
#@-- init window1.__init_ _ {
def __init__(self, path='gui.glade ',
root='window1',
domain=app_name , kwargs={}):
path = os.path.join(gl ade_dir, path)
SimpleGladeApp. __init__(self, path, root, domain, **kwargs)
self.q=Queue.Qu eue()
self.action=act .action(self.q)
gobject.timeout _add (1000,self.acti on.go)
gobject.timeout _add (1000,self.proc ess)
#@-- init window1.__init_ _ }
#@-- new window1.new {
def new(self):
print 'A new %s has been created' % self.__class__. __name__
#@-- new window1.new }
#@-- custom window1 {
# Write your own methods here
#@-- custom window1 }
#@-- callback window1.on_butt on1_clicked {
def on_button1_clic ked(self, widget, args=[]):
print 'on_button1_cli cked called with self.%s' %
widget.get_name ()
self.action.sto p()
print "arrete de thread"
#@-- callback window1.on_butt on1_clicked }
def process (self):
dir (self.q)
if self.q.empty() == False :
print "from main ",self.q.ge t()
return True
#@-- window window1 }
#@-- main gui.py {
#@-- init main {
def main():
#@-- init main }
#@-- body main {
Window1 = window1()
Window1.run()
#@-- body main }
#@-- main gui.py }
#@-- run gui.py {
if __name__ == '__main__':
main()
#@-- run gui.py }
#@-- 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="GtkWindo w" id="window1">
<property name="visible"> True</property>
<property name="title" translatable="y es">window1</property>
<property name="type">GTK _WINDOW_TOPLEVE L</property>
<property name="window_po sition">GTK_WIN _POS_NONE</property>
<property name="modal">Fa lse</property>
<property name="resizable ">True</property>
<property name="destroy_w ith_parent">Fal se</property>
<property name="decorated ">True</property>
<property name="skip_task bar_hint">False </property>
<property name="skip_page r_hint">False</property>
<property name="type_hint ">GDK_WINDOW_TY PE_HINT_NORMAL</property>
<property name="gravity"> GDK_GRAVITY_NOR TH_WEST</property>
<property name="focus_on_ map">True</property>
<property name="urgency_h int">False</property>
<child>
<widget class="GtkVBox" id="vbox1">
<property name="visible"> True</property>
<property name="homogeneo us">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="visibilit y">True</property>
<property name="max_lengt h">0</property>
<property name="text" translatable="y es">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">T rue</property>
<property name="fill">Tru e</property>
</packing>
</child>
<child>
<widget class="GtkButto n" id="button1">
<property name="visible"> True</property>
<property name="can_focus ">True</property>
<property name="label" translatable="y es">button1</property>
<property name="use_under line">True</property>
<property name="relief">G TK_RELIEF_NORMA L</property>
<property name="focus_on_ click">True</property>
<signal name="clicked" handler="on_but ton1_clicked"
last_modificati on_time="Wed, 20 Sep 2006 19:59:06 GMT"/>
</widget>
<packing>
<property name="padding"> 0</property>
<property name="expand">F alse</property>
<property name="fill">Fal se</property>
<property name="pack_type ">GTK_PACK_ END</property>
</packing>
</child>
</widget>
</child>
</widget>
</glade-interface>
Comment