S
seb
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):
#@-- class window1 }
#@-- 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
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(SimpleGladeApp):
#@-- class window1 }
#@-- 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)
#@-- 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_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"
#@-- callback window1.on_button1_clicked }
def process (self):
dir (self.q)
if self.q.empty() == False :
print "from main ",self.q.get()
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="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>
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):
#@-- class window1 }
#@-- 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
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(SimpleGladeApp):
#@-- class window1 }
#@-- 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)
#@-- 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_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"
#@-- callback window1.on_button1_clicked }
def process (self):
dir (self.q)
if self.q.empty() == False :
print "from main ",self.q.get()
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="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>