Alguns dias atrás comecei a mexer na muito falada (e que será adotada pelo Firefox) biblioteca de desenho vetorial Cairo, com o propósito de fazer um widget em PyGTK representando um heptágono cujos vértices pudessem ser movidos. Eventualmente passei um tempo aprendendo o básico até estancar num problema irritante, que pra variar tinha uma solução simples.

Heptágono

Para criar meu widget, chamado ValueWheel, precisei extender GtkDrawingArea e criar meus próprios métodos para interceptar alguns eventos, como “expose-event”, que acontece toda vez que uma janela, ou parte dela, precisa ser redesenhada. Quando clicava numa das bolinhas nos vértices e a arrastava, meu método que cuidava do “motion-notify-event” reposicionava a tal bolinha e redesenhava tudo. O grande problema é que esses redesenhos estavam muito lentos, com direito a piscada e tudo.

Bastante tempo depois, procurando no Google Code Search, descobri que o jeito certo de fazer a coisa não era ordenar o redesenho diretamente, e sim forçar a emissão do evento expose. Coloquei essas quatro linhas no método de movimento:

alloc = self.get_allocation()
rect = gtk.gdk.Rectangle(0, 0, alloc.width, alloc.height)
self.window.invalidate_rect(rect, True)
self.window.process_updates(True)

Era necessário apenas “invalidar” a área que foi redesenhada e avisar que um update era necessário, que magicamente o widget se redesenhou e sem piscar.

Aos interessados em Cairo eu recomendo:

E o código sobre o qual este post fala é esse: ValueWheel.py