Generally speaking, you should not draw directly to the window outside of an expose event. And do not keep the cairo context for later use: create one for each event run.
When you want to draw your points, just do: widget.queue_draw()
, and a new expose event will be delivered to you ASAP. But note that in the expose event you will have to paint all the points, not just the new one.
There a useful optimization to your type of code: from the timer do not call queue_draw
as it is fairly inefficient. Instead just draw the new point. However that doesn't excuse you to draw all the points in the do_expose_event
, as an expose event can happen at any time and you do not want to lose the already painted points.
To do the one-point draw you have to create a new cairo context, but you do not need to save it:
def update(self):
cr = self.window.cairo_create()
x = randint(0, DOCK_W)
y = randint(0, DOCK_H)
self.points.append((x,y)) #for the expose event ;-)
cr.rectangle(x, y, 1, 1)
cr.set_source_rgba(0, 0, 0, 1)
cr.fill()
cr.paint()
Another common optimization, particularly if you have a lot of points is to keep the painted image in a bitmap, so when the expose event happens, you simply blit the bitmap, instead of iterating all along the list of points.