Cannot paint paths with cairo on gtk widgets in python 3

750 views Asked by At

I have trouble rendering a custom GTK3 drawing area with custom cairo code. It seems that the cairo context doesn't want to trouble with the shape I specify. It writes the whole source onto the whole destination, regardless of the shape.

So for example, if I set a fully white source area to paint a small white rectangle, and I ask cairo to fill() that rectangle, it paints the whole DrawingArea widget instead of that rectangle. What am I missing here ?

#!/usr/bin/env python3
from gi.repository import Gtk as gtk
from gi.repository import Gdk as gdk
import cairo

class Canvas(gtk.DrawingArea):
    def __init__(self):
        gtk.DrawingArea.__init__(self)
        self.set_size_request(600,400)
        self.connect('draw',Canvas.on_draw)

    def on_draw(self,context):
        context.set_source_rgb( 0.1, 0.0, 0.1 )
        context.fill()
        context.set_source_rgb( 1.0, 1.0, 1.0 )
        context.rectangle(50,50,100,100)
        context.fill()
        context.paint()
        return False

#look at this code
class MainWindow(gtk.Window):
    def __init__(self):
        gtk.Window.__init__(self, title="Game Centurion")

        self.dummy0 = gtk.Label(label="dummy₀")
        self.canvas = Canvas()
        self.box = gtk.Box()

        self.box.pack_start(self.canvas, True, True, 0)
        self.box.pack_start(self.dummy0, True, True, 0)

        self.add(self.box)

        self.connect('delete-event', gtk.main_quit)

if __name__ == '__main__':
    w = MainWindow()
    w.show_all()
    gtk.main()

Here is the result window, you can see it is fully white instead of having a small white square over a dark purple background as I specified in the code above.

DrawingArea Result

Thank you for any help.

1

There are 1 answers

1
Lærne On BEST ANSWER

Okay, I got it.

I misunderstood the role of the method paint of object context. I though it was some kind of "commit" to actually perform all operation specified before. Actually those operations are painted "on spot" (or after the return call, I dunno), and paint is an operation that copy the whole source into the destination.

No wonder it didn't work. out so well.

Here is the correct drawing callback :

def on_draw(self,emitter,context):
    context.set_source_rgb( 0.1, 0.0, 0.1 )
    context.paint()
    context.rectangle(50,50,100,100)
    context.set_source_rgb( 1.0, 1.0, 1.0 )
    context.fill()
    return False