[pygtk] Animation performance - limitation or my code?
John Finlay
finlay at moeraki.com
Wed Sep 2 16:04:48 WST 2009
Kim Adil wrote:
> I once wrote a gtk program in C that displayed about 30 animations on a
> drawing area and they moved around the screen, and performance was
> excellent. The drawingarea size was 1600x1200 and the animations were
> very smooth.
>
> I have started to write a similar app using pygtk in a more object
> oriented way, and the drawing area size really seems to have a large
> impact on performance. When the drawing area is 100x100, anims are
> smooth. If the drawing area is dragged to 1000x1000 the frame rate drops
> very quickly. Is this to be expected with the python being interpreted,
> or is it just that my code is inefficient. See sample below (requires 2
> animated gif files a.gif and a2.gif, just substitute any from the web
> for demonstartion, and a glade file attached):
>
>
> #!/usr/bin/env python
> import sys
> import pygtk
> import glib
> import gtk
> import gtk.glade
> # main window to display objects in motion
>
> i=1
> class MainWin:
> def __init__(self):
> self.gladefile = "hv.glade"
> self.wTree = gtk.glade.XML(self.gladefile, "main_win")
> dic = {"on_drawingarea1_expose_event" : self.expose,
> "on_drawingarea1_configure_event": self.configure,
> }
> self.wTree.signal_autoconnect(dic)
> self.window = self.wTree.get_widget("main_win")
> self.da = self.wTree.get_widget("drawingarea1")
> self.window.show_all()
> x, y, width, height = self.da.get_allocation()
> self.pixmap = gtk.gdk.Pixmap(self.da.window, width, height)
> self.machlist = []
> self.setup_objects()
> glib.timeout_add(30, self.draw_objects)
>
> def setup_objects(self):
> self.machlist.append(Object('t1','v','stopped',10,10,'a.gif'))
>
> self.machlist.append(Object('t2','v','travelling',300,10,'a2.gif'))
> self.machlist.append(Object('t3','v','stopped',100,300,'a.gif'))
> self.machlist.append(Object('t4','v','stopped',600,600,'a2.gif'))
> self.machlist.append(Object('t5','v','stopped',100,60,'a.gif'))
> self.machlist.append(Object('t6','f','stopped',60,100,'a.gif'))
>
> self.machlist.append(Object('t7','f','travelling',100,100,'a.gif'))
>
> def draw_objects(self):
> x, y, width, height = self.da.get_allocation()
> self.pixmap = gtk.gdk.Pixmap(self.da.window, width, height)
> self.pixmap.draw_rectangle(self.da.get_style().white_gc,True, 0,
> 0, width, height)
> for object in self.machlist:
>
> self.pixmap.draw_pixbuf(self.da.get_style().fg_gc[gtk.STATE_NORMAL],object.pb,
>
> 0, 0, object.x,object.y)
Add this line:
self.da.queue_draw_area(x, y, width, height)
> return True
> def expose(self,a,b):
> x, y, width, height = self.da.get_allocation()
>
> self.da.window.draw_drawable(self.da.get_style().fg_gc[gtk.STATE_NORMAL],self.pixmap,
>
> x, y, x, y, width, height)
> self.da.queue_draw_area(x, y, width, height)
Remove the above line.
> return False
>
> def configure(self,a,b):
> x, y, width, height = self.da.get_allocation()
>
> self.da.window.draw_drawable(self.da.get_style().fg_gc[gtk.STATE_NORMAL],self.pixmap,
>
> x, y, x, y, width, height)
> return False
>
> def cleanup(self):
> for object in self.machlist:
> glib.source_remove(object.timeout)
>
> def list_objects(self):
> self.draw_objects()
> for object in self.machlist:
>
> self.pixmap.draw_pixbuf(self.da.get_style().fg_gc[gtk.STATE_NORMAL],object.pb,
>
> 0, 0, 0, 0)
> #self.da.queue_draw()
> class Object:
> def __init__(self,name,model,state,x,y,anim):
> self.name=name
> self.model=model
> self.state=state
> self.x=x
> self.y=y
> self.anim=anim
> self.image='l'
> self.frame=0
> self.imagef = gtk.Image()
> self.pixbufanim = gtk.gdk.PixbufAnimation(anim)
> print 'width %d - height
> %d'%(self.pixbufanim.get_width(),self.pixbufanim.get_height())
> self.pbiter = self.pixbufanim.get_iter()
> print 'delay time %d'%(self.pbiter.get_delay_time())
> self.pb=self.pbiter.get_pixbuf()
> self.t=glib.timeout_add(self.pbiter.get_delay_time(),
> self.update_pb)
>
> def update_pb(self):
> self.pbiter.advance()
> self.pb=self.pbiter.get_pixbuf()
> self.t=glib.timeout_add(self.pbiter.get_delay_time(),
> self.update_pb)
> return False
>
>
> print 'create mainwin'
> m=MainWin()
> gtk.main()
>
I think the program is generating too many expose events and too many
draw_pixbuf calls are slowing down the animations when a large pixbuf
draw is needed.
John
More information about the pygtk
mailing list