Drawing In Pygobject (python3)
I'm trying to write simple graphic editor using PyGObject and python 3. I need to draw lines with different color and width using mouse. I found many examples like this but nothing
Solution 1:
You need to use a Double Buffer technique:
http://en.wikipedia.org/wiki/Multiple_buffering#Double_buffering_in_computer_graphics
That is you have an image, and you draw over that image: that image is the "behind the scenes" buffer. You can have a lot of methods that draw something to that image. Then, on the callback that responds to 'draw' signal, that is, the method that actually draws something to the graphics memory you just throw your "behind the scenes" image.
Theory in code (test.py):
import cairo
from gi.repository import Gtk
from os.path import abspath, dirname, join
WHERE_AM_I = abspath(dirname(__file__))
classMyApp(object):
"""Double buffer in PyGObject with cairo"""def__init__(self):
# Build GUI
self.builder = Gtk.Builder()
self.glade_file = join(WHERE_AM_I, 'test.glade')
self.builder.add_from_file(self.glade_file)
# Get objects
go = self.builder.get_object
self.window = go('window')
# Create buffer
self.double_buffer = None# Connect signals
self.builder.connect_signals(self)
# Everything is ready
self.window.show()
defdraw_something(self):
"""Draw something into the buffer"""
db = self.double_buffer
if db isnotNone:
# Create cairo context with double buffer as is DESTINATION
cc = cairo.Context(db)
# Scale to device coordenates
cc.scale(db.get_width(), db.get_height())
# Draw a white background
cc.set_source_rgb(1, 1, 1)
# Draw something, in this case a matrix
rows = 10
columns = 10
cell_size = 1.0 / rows
line_width = 1.0
line_width, notused = cc.device_to_user(line_width, 0.0)
for i inrange(rows):
for j inrange(columns):
cc.rectangle(j * cell_size, i * cell_size, cell_size, cell_size)
cc.set_line_width(line_width)
cc.set_source_rgb(0, 0, 0)
cc.stroke()
# Flush drawing actions
db.flush()
else:
print('Invalid double buffer')
defmain_quit(self, widget):
"""Quit Gtk"""
Gtk.main_quit()
defon_draw(self, widget, cr):
"""Throw double buffer into widget drawable"""if self.double_buffer isnotNone:
cr.set_source_surface(self.double_buffer, 0.0, 0.0)
cr.paint()
else:
print('Invalid double buffer')
returnFalsedefon_configure(self, widget, event, data=None):
"""Configure the double buffer based on size of the widget"""# Destroy previous bufferif self.double_buffer isnotNone:
self.double_buffer.finish()
self.double_buffer = None# Create a new buffer
self.double_buffer = cairo.ImageSurface(\
cairo.FORMAT_ARGB32,
widget.get_allocated_width(),
widget.get_allocated_height()
)
# Initialize the buffer
self.draw_something()
returnFalseif __name__ == '__main__':
gui = MyApp()
Gtk.main()
Glade file (test.glade):
<?xml version="1.0" encoding="UTF-8"?><interface><!-- interface-requires gtk+ 3.0 --><objectclass="GtkWindow"id="window"><propertyname="can_focus">False</property><propertyname="window_position">center-always</property><propertyname="default_width">800</property><propertyname="default_height">600</property><signalname="destroy"handler="main_quit"swapped="no"/><child><objectclass="GtkDrawingArea"id="drawingarea1"><propertyname="visible">True</property><propertyname="can_focus">False</property><signalname="draw"handler="on_draw"swapped="no"/><signalname="configure-event"handler="on_configure"swapped="no"/></object></child></object></interface>
Dependencies:
Python 2:
sudo apt-get install python-cairo
Python 3:
sudo apt-get install python3-gi-cairo
Now execute with:
python test.py
or
python3 test.py
What it looks like:
All the documentation for cairo can be found in http://cairographics.org/documentation/pycairo/3/reference/index.html
Kind regards
Post a Comment for "Drawing In Pygobject (python3)"