Skip to content

Instantly share code, notes, and snippets.

@oz123
Created December 11, 2016 23:18
Show Gist options
  • Save oz123/acf6d757a1a1137bc0c514b5fb606bb4 to your computer and use it in GitHub Desktop.
Save oz123/acf6d757a1a1137bc0c514b5fb606bb4 to your computer and use it in GitHub Desktop.
#!/usr/bin/python
from __future__ import division
import math
import time
import cairo
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk
from gi.repository.GdkPixbuf import Pixbuf
def clear_surface(w, h, surface):
cr = cairo.Context(surface)
cr.set_source_rgb(0, 0, 0)
cr.paint()
del cr
def draw_brush(widget, x, y, odata, width=12.5, r=220/255, g=240/255, b=90/255, alpha=0.5):
cr = cairo.Context(widget.surface)
cr.set_source_rgba(r, g, b, alpha)
cr.set_line_width(width)
cr.set_line_cap(1)
cr.set_line_join(cairo.LINE_JOIN_ROUND)
cr.new_path()
head = odata[-2]
point = odata[-1]
cr.move_to(head['x'], head['y']+2.5)
cr.line_to(point['x'], point['y']+1.5)
cr.stroke()
class Example(Gtk.Window):
def __init__(self):
super(Example, self).__init__()
self.set_border_width(8)
self.odata = []
self.box = Gtk.Box(spacing=6)
self.add(self.box)
da = Gtk.DrawingArea()
self.box.pack_start(da, True, True, 0)
window = Gdk.get_default_root_window()
self.set_default_size(400, 400)
da.surface = None
da.connect('draw', self.draw)
da.connect('configure-event', self.configure_event_cb)
da.connect('motion-notify-event', self.motion_notify_event_cb)
da.connect('button-press-event', self.button_press_event_cb)
da.connect('button-release-event', self.button_release)
da.set_events(da.get_events() |
Gdk.EventMask.BUTTON_PRESS_MASK |
Gdk.EventMask.POINTER_MOTION_MASK |
Gdk.EventMask.BUTTON_RELEASE_MASK)
self.da = da
self.connect('destroy', self.close_window)
self.show_all()
def button_release(self, widget, event):
self.odata = []
def draw(self, widget, cr):
cr.set_source_surface(self.da.surface, 0, 0)
cr.paint()
return False
def configure_event_cb(self, widget, event):
"""
Called the windows is first created. Here we also load the
background image, via the call to clear
"""
self.odata = []
if self.da.surface is not None:
del self.da.surface
self.da.surface = None
win = widget.get_window()
w = widget.get_allocated_width()
h = widget.get_allocated_height()
widget.surface = win.create_similar_surface(
cairo.CONTENT_COLOR,
w, h)
clear_surface(w, h, widget.surface)
return True
def button_press_event_cb(self, widget, event):
"""
When the signal handler returns True, it means no further processing is done.
E.g. there will be no propagation further. On the contrary, sending False,
propagates the signal further.
See documentation here:
https://developer.gnome.org/gtk3/stable/GtkWidget.html#GtkWidget-button-press-event
"""
if widget.surface is None:
return False
if event.button == Gdk.BUTTON_PRIMARY:
if self.odata:
self.odata = []
point = {'x': event.x, 'y': event.y, 'd': False}
self.odata.append(point)
pass
elif event.button == Gdk.BUTTON_SECONDARY:
win = widget.get_window()
width = widget.get_allocated_width()
height = widget.get_allocated_height()
pixbuf = Gdk.pixbuf_get_from_window(win, 0, 0,
width, height)
clear_surface(width*0.95, height*0.95, widget.surface)
widget.queue_draw()
return False
def motion_notify_event_cb(self, widget, event):
if widget.surface is None:
return False
if event.state & Gdk.EventMask.BUTTON_PRESS_MASK:
point = {'x': event.x, 'y': event.y, 'd': False}
self.odata.append(point)
draw_brush(self.da, event.x, event.y, self.odata)
widget.queue_draw()
return True
def close_window(self, window):
if self.da is not None:
del self.da.surface
self.da.surface = None
Gtk.main_quit()
def main():
Example()
Gtk.main()
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment