My program draws circles moving on the window. I think I must be missing some basic gtk/cairo concept because it seems to be running too slowly/stutteringly for what I am doing. Any ideas? Thanks for any help!
#!/usr/bin/python
import gtk
import gtk.gdk as gdk
import math
import random
import gobject
# The number of circles and the window size.
num = 128
size = 512
# Initialize circle coordinates and velocities.
x = []
y = []
xv = []
yv = []
for i in range(num):
x.append(random.randint(0, size))
y.append(random.randint(0, size))
xv.append(random.randint(-4, 4))
yv.append(random.randint(-4, 4))
# Draw the circles and update their positions.
def expose(*args):
cr = darea.window.cairo_create()
cr.set_line_width(4)
for i in range(num):
cr.set_source_rgb(1, 0, 0)
cr.arc(x[i], y[i], 8, 0, 2 * math.pi)
cr.stroke_preserve()
cr.set_source_rgb(1, 1, 1)
cr.fill()
x[i] += xv[i]
y[i] += yv[i]
if x[i] > size or x[i] < 0:
xv[i] = -xv[i]
if y[i] > size or y[i] < 0:
yv[i] = -yv[i]
# Self-evident?
def timeout():
darea.queue_draw()
return True
# Initialize the window.
window = gtk.Window()
window.resize(size, size)
window.connect("destroy", gtk.main_quit)
darea = gtk.DrawingArea()
darea.connect("expose-event", expose)
window.add(darea)
window.show_all()
# Self-evident?
gobject.idle_add(timeout)
gtk.main()
One of the problems is that you are drawing the same basic object again and again. I’m not sure about GTK+ buffering behavior, but also keep in mind that basic function calls incur a cost in Python. I’ve added a frame counter to your program, and I with your code, I got around 30fps max.
There are several things you can do, for instance compose larger paths before actually calling any fill or stroke method (i.e. will all arcs in a single call). Another solution, which is vastly faster is to compose your ball in an off-screen buffer and then just paint it to the screen repeatedly:
This gives about 273 fps on my machine. Because of this, you should think about using
gobject.timeout_addrather thanidle_add.