Reputation: 1819
I am trying to follow the Gtk+ v3 tutorial found in the reference documentation. Specifically the first Drawing example using cairo
to handle the drawing onto a Gtk.DrawingArea
.
https://developer.gnome.org/gtk3/stable/ch01s03.html
For reference, I am using these resources:
https://python-gtk-3-tutorial.readthedocs.org/en/latest/
http://lazka.github.io/pgi-docs/
Please take a look at my (partial) translation of the ch01s03
program into python. The main problem I have is with configure_event_cb()
where the program should create a cairo.Surface
object connected to a Gdk.Window
. I do not know how to get at this Gdk.Window
or even where to look in the reference documentation.
from gi.repository import Gtk, Gdk, cairo
surface = None
def clear_surface():
global surface
surface = cairo.Surface()
surface.set_source_rgb(1,1,1)
surface.paint()
def configure_event_cb(wid,evt):
global surface
if surface is not None:
surface.destroy()
surface = None
'''
Here, I am trying to implement the following C code:
surface = gdk_window_create_similar_surface(
gtk_widget_get_window(widget),
CAIRO_CONTENT_COLOR,
gtk_widget_get_allocated_width(widget),
gtk_widget_get_allocated_height(widget) );
'''
clear_surface()
return True
def close_window(wid):
global surface
if surface is not None:
surface.destroy()
Gtk.main_quit()
if __name__ == '__main__':
win = Gtk.Window(Gtk.WindowType.TOPLEVEL)
win.set_title('Drawing Area')
win.connect('destroy',close_window)
win.set_border_width(8)
frame = Gtk.Frame()
frame.set_shadow_type(Gtk.ShadowType.IN)
win.add(frame)
da = Gtk.DrawingArea()
da.set_size_request(100,100)
frame.add(da)
da.connect('configure-event',configure_event_cb)
win.show_all()
Gtk.main()
Upvotes: 4
Views: 5338
Reputation: 1819
With the help of the (accepted) answer from @cedlemo I was able to recreate the ch01s03
Gtk+
example in python
. However, I had to import cairo
actual since the gi.repository.cairo.Context()
constructor didn't exist. This was not obvious at first, but maybe it makes sense. Here is the fully working version. See for the original C
version with comments.
from gi.repository import Gtk, Gdk
import cairo
surface = None
def clear_surface():
global surface
cr = cairo.Context(surface)
cr.set_source_rgb(1,1,1)
cr.paint()
del cr
def configure_event_cb(wid,evt):
global surface
if surface is not None:
del surface
surface = None
win = wid.get_window()
width = wid.get_allocated_width()
height = wid.get_allocated_height()
surface = win.create_similar_surface(
cairo.CONTENT_COLOR,
width,
height)
clear_surface()
return True
def draw_cb(wid,cr):
global surface
cr.set_source_surface(surface,0,0)
cr.paint()
return False
def draw_brush(wid,x,y):
global surface
cr = cairo.Context(surface)
cr.set_source_rgb(0,0,0)
cr.rectangle(x-3,y-3,6,6)
cr.fill()
del cr
wid.queue_draw_area(x-3,y-3,6,6)
def button_press_event_cb(wid,evt):
global surface
if surface is None:
return False
if evt.button == Gdk.BUTTON_PRIMARY:
draw_brush(wid,evt.x,evt.y)
elif evt.button == Gdk.BUTTON_SECONDARY:
clear_surface()
wid.queue_draw()
return True
def motion_notify_event_cb(wid,evt):
global surface
if surface is None:
return False
if evt.state & Gdk.EventMask.BUTTON_PRESS_MASK:
draw_brush(wid,evt.x,evt.y)
return True
def close_window(wid):
global surface
if surface is not None:
del surface
surface = None
Gtk.main_quit()
if __name__ == '__main__':
win = Gtk.Window()
win.set_title('Drawing Area')
win.connect('destroy',close_window)
win.set_border_width(8)
frame = Gtk.Frame()
frame.set_shadow_type(Gtk.ShadowType.IN)
win.add(frame)
da = Gtk.DrawingArea()
da.set_size_request(100,100)
frame.add(da)
da.connect('draw',draw_cb)
da.connect('configure-event',configure_event_cb)
da.connect('motion-notify-event',motion_notify_event_cb)
da.connect('button-press-event',button_press_event_cb)
da.set_events(da.get_events() | Gdk.EventMask.BUTTON_PRESS_MASK | Gdk.EventMask.POINTER_MOTION_MASK)
win.show_all()
Gtk.main()
Upvotes: 4
Reputation: 3334
I have understood that the DrawingArea use the draw event now instead of the configure-event here is a simple code that works:
from gi.repository import Gtk
def draw_cb(widget, cr):
cr.set_source_rgba(0,0,0,0.5)
cr.rectangle(50,75,100,100)
cr.fill()
return False
win = Gtk.Window()
win.set_title("test")
win.set_default_size(800,600)
win.connect('delete-event', Gtk.main_quit)
da=Gtk.DrawingArea()
da.connect('draw', draw_cb)
win.add(da)
win.show_all()
Gtk.main()
But instead if you really want to create a cairo context in the callback of the expose-event, just use this to get the gtk.gdk.window:
myGdkWindow = mywin.get_window()
cr = myGdkWindow.cairo_create()
Upvotes: 4