The problem is in 1/2 GTK and threads. unfortunetly threads are needed in this instance, idle timers [orig tried with them] have their issues which added their own problems, threads gave alot more benefits then they then problems they solved (I have a forum-thread on a python forum about three methods I tried, for this instance threading is the only solution)
Basically GTK can work with threads, the problem arrises when the thread want's to change the GUI (say a txt lable). GTK can be made "thread-safe" via calling gtk.gdk.threads_init() before gtk.main(). THEN every time the thread wants to change something, put it between
gtk.threads_enter()
gtk.threads_leave()
calls.
THIS only works for default GTK widgets and since a matplotlib window isn't a standard GTK widget it hard-locks the GUI.
I have a solution to it, it is quite neat (it could be a fn wrapper, but don't know much abt fn wrappers)
#!/usr/bin/env python
import threading
import time
import math
import sys
import os
import pygtk
if sys.platform == 'win32':
os.environ['PATH'] += ';lib;'
else:
pygtk.require('2.0')
import gtk
import gobject
assert gtk.pygtk_version >= (1,99,16), 'pygtk should be >= 1.99.16'
#import gtk.glade
from pylab import *
rcParams['numerix'] = 'numpy'
import matplotlib
matplotlib.use('GTK')
from matplotlib.figure import Figure
from matplotlib.axes import Subplot
from matplotlib.backends.backend_gtk import FigureCanvasGTK as FigureCanvas
TIME = range(360)
VOLT = [math.sin(math.radians(x)) for x in TIME]
VOLT2 = [2]*360
VOLT3 = [x for x in range(360)]
def do_gui(fn,*args,**kw):
def idle_func():
print "idle"
gtk.threads_enter()
try:
fn(*args,**kw)
finally:
gtk.threads_leave()
gobject.idle_add(idle_func)
class my_thread(threading.Thread):
def __init__(self,GUI):
super(my_thread, self).__init__()
self.GUI = GUI
def run(self):
time.sleep(10)
#gtk.threads_enter()
#try:
# self.GUI.Graph([TIME,VOLT3])
#finally:
# gtk.threads_leave()
do_gui(self.GUI.Graph,[TIME,VOLT3])
gtk.gdk.threads_init()
class GUI(object):
def GUI_Plot(self,widget,event,data=""
self.Graph([TIME,VOLT2])
def delete_event(self,widget,event,data=""
return False
def destroy(self,widget,data=""
gtk.main_quit()
def __init__(self):
super(GUI,self).__init__()
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
self.window.set_title("Matplotlib GTK test")
self.window.connect("delete_event",self.delete_event)
self.window.connect("destroy",self.destroy)
self.window.set_border_width(10)
self.box1 = gtk.VBox(False,0)
self.window.add(self.box1)
self.button = gtk.Button("GUI Plot")
self.button.connect("clicked",self.GUI_Plot,None)
self.box1.pack_start(self.button,True,True,0)
self.button.show()
self.box1.show()
self.window.show()
self.Graph([TIME,VOLT])
def Graph(self,DATA):
try:
self.canvas.destroy()
self.toolbar.destroy()
except:pass
self.figure = Figure(figsize=(6,3), dpi=100)#{{{
self.axis = self.figure.add_subplot(111)
self.axis.grid(True)
self.axis.set_xlabel('Time (s)')
self.axis.plot(DATA[0],DATA[1],linewidth=2.0)
self.canvas = FigureCanvas(self.figure) # a gtk.DrawingArea
self.canvas.show()
self.graphview = self.box1
self.graphview.pack_start(self.canvas, True, True)
def main(self):
gtk.main()
if __name__ == "__main__":
A = GUI()
B = my_thread(A)
B.start()
gtk.threads_enter()
A.main()
gtk.threads_leave()
basically another fn is created that has the threads_enter and threads_leave called, BUT they themselves are called within a gtk-idle call, this stops the GUI from hard-locking.
I don't know if it is the best solution, but it is a solution.
thanks
On 9/5/06, John Hunter <
[EMAIL PROTECTED]> wrote:
>>>>> "Jon" == Jon Roadley-Battin < [EMAIL PROTECTED]> writes:
Jon> is there any thread_init for matplotlib. short of having a
Jon> timer within the GUI class that checks if any new data is
Jon> present I cant see a way around this. It has to be done this
There isn't any such method. Would it work for you to update your
line data / plot data and run canvas.draw_idle in a gtk timer, eg
every second? Since you are only polling your RS232 every second or
so, it seems like you could update your graph in a timer on roughly
the same time scale w/o too much pain.
I don't know mcuh about threading, but trying to make threads play
nice with all the GUIs mpl supports seems daunting, and I prefer to
offload that to external apps -- eg ipython in pylab mode. But if
there is something we can add that will make your use case work better
if the timer route doesn't work, feel free to suggest something...
JDH
------------------------------------------------------------------------- Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________ Matplotlib-users mailing list Matplotlib-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-users