I have a solution that works.
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

Reply via email to