12用 Cairo 库绘图
在教程的这个部分,我们将用Cairo做一些绘图的事情。
Cairo是一种用来创建2D矢量图形的库。我们可以用它来绘制我们的部件,图标或者各种效果或动画。
Simple drawing
Stroke 操作是绘制模型的边界,而fill操作是填充模型的内部。下面我们将展示这两个操作。
Code:simpledrawing.py
#!/usr/bin/python
# ZetCode PyGTK tutorial
#
# This code example draws a circle
# using the cairo library
#
# author: jan bodnar
# website: zetcode.com
# last edited: February 2009
import gtk
import math
class PyApp(gtk.Window):
def __init__(self):
super(PyApp, self).__init__()
self.set_title("Simple drawing")
self.resize(230, 150)
self.set_position(gtk.WIN_POS_CENTER)
self.connect("destroy", gtk.main_quit)
darea = gtk.DrawingArea()
darea.connect("expose-event", self.expose)
self.add(darea)
self.show_all()
def expose(self, widget, event):
cr = widget.window.cairo_create()
cr.set_line_width(9)
cr.set_source_rgb(0.7, 0.2, 0.0)
w = self.allocation.width
h = self.allocation.height
cr.translate(w/2, h/2)
cr.arc(0, 0, 50, 0, 2*math.pi)
cr.stroke_preserve()
cr.set_source_rgb(0.3, 0.4, 0.6)
cr.fill()
PyApp()
gtk.main()
在我们的例子中,我们将画一个圆,并且它将有立体的颜色。
darea = gtk.DrawingArea()
我们将要在DrawingArea部件上做绘图操作。
darea.connect("expose-event", self.expose)
我们在一个方法中做所有的绘图工作,这个方法是expose-event信号的处理函数。
cr = widget.window.cairo_create()
我们从绘图区域的gdk.Window创建了cairo context对象。这个context是一种用来在所有可绘图对象上绘画的对象。
cr.set_line_width(9)
我们设置线的宽度为9个像素。
cr.set_source_rgb(0.7, 0.2, 0.0)
我们将颜色设置为暗红色。
w = self.allocation.width h = self.allocation.height cr.translate(w/2, h/2)
我们得到绘图区域的宽度和高度。我们移动原点到窗口的中心。
cr.arc(0, 0, 50, 0, 2*math.pi) cr.stroke_preserve()
stroke_preserve()方法是根据当前的线宽度(line width)、线连接(line join)、线终结(line cap)和混合设定(dash settings)来绘出(stroke)当前的路径。【译者注:此处翻译可能有误,请自行理解英文意义】。不同于stroke()方法,它在cairo context内保持线的路径。
cr.set_source_rgb(0.3, 0.4, 0.6) cr.fill()
这里用一些蓝色来填充圆的内部。
Figure:Simple Drawing
Basic shapes
下面的例子将绘制一些基本图形(Basic shapes)到窗口上。
Code:basicshapes.py
#!/usr/bin/python
# ZetCode PyGTK tutorial
#
# This code example draws basic shapes
# with the cairo library
#
# author: jan bodnar
# website: zetcode.com
# last edited: February 2009
import gtk
import math
class PyApp(gtk.Window):
def __init__(self):
super(PyApp, self).__init__()
self.set_title("Basic shapes")
self.set_size_request(390, 240)
self.set_position(gtk.WIN_POS_CENTER)
self.connect("destroy", gtk.main_quit)
darea = gtk.DrawingArea()
darea.connect("expose-event", self.expose)
self.add(darea)
self.show_all()
def expose(self, widget, event):
cr = widget.window.cairo_create()
cr.set_source_rgb(0.6, 0.6, 0.6)
cr.rectangle(20, 20, 120, 80)
cr.rectangle(180, 20, 80, 80)
cr.fill()
cr.arc(330, 60, 40, 0, 2*math.pi)
cr.fill()
cr.arc(90, 160, 40, math.pi/4, math.pi)
cr.fill()
cr.translate(220, 180)
cr.scale(1, 0.7)
cr.arc(0, 0, 50, 0, 2*math.pi)
cr.fill()
PyApp()
gtk.main()
在这个例子中,我们创建了一个长方形、一个正方形、一个圆形、一个弧形和一个椭圆形。
cr.rectangle(20, 20, 120, 80) cr.rectangle(180, 20, 80, 80) cr.fill()
这几行绘制了一个长方形和一个正方形。
cr.arc(330, 60, 40, 0, 2*math.pi) cr.fill()
在这里,arc()方法绘制出了一个整圆。
cr.scale(1, 0.7) cr.arc(0, 0, 50, 0, 2*math.pi) cr.fill()
如果你想画一个椭圆的,你首先得做一些缩放。这里scale()方法将Y轴的距离缩小了。
Figure:Basic Shapes
Colors
Color就是一个描述红、绿、蓝(RGB)的强度值组合的对象。Cairo有效的RGB值是在0到1之间变化。
Code:colors.py
#!/usr/bin/python
# ZetCode PyGTK tutorial
#
# This program shows how to work
# with colors in cairo
#
# author: jan bodnar
# website: zetcode.com
# last edited: February 2009
import gtk
class PyApp(gtk.Window):
def __init__(self):
super(PyApp, self).__init__()
self.set_title("Colors")
self.resize(360, 100)
self.set_position(gtk.WIN_POS_CENTER)
self.connect("destroy", gtk.main_quit)
darea = gtk.DrawingArea()
darea.connect("expose-event", self.expose)
self.add(darea)
self.show_all()
def expose(self, widget, event):
cr = widget.window.cairo_create()
cr.set_source_rgb(0.2, 0.23, 0.9)
cr.rectangle(10, 15, 90, 60)
cr.fill()
cr.set_source_rgb(0.9, 0.1, 0.1)
cr.rectangle(130, 15, 90, 60)
cr.fill()
cr.set_source_rgb(0.4, 0.9, 0.4)
cr.rectangle(250, 15, 90, 60)
cr.fill()
PyApp()
gtk.main()
我们用三个不同的颜色绘制了三个长方形。
cr.set_source_rgb(0.2, 0.23, 0.9)
set_source_rgb()方法是为cairo context对象设置一个颜色。方法的三个参数是颜色的强度值。
cr.rectangle(10, 15, 90, 60) cr.fill()
我们创建了一个长方形的形状,并且用先前指定的颜色来填充它。
Figure:Colors
Transparent rectangles
透明度是能够通过肉眼看到的一种特性。最简单的理解透明度的方法是去想象一下一块玻璃或者水。在技术上,光线能够穿透玻璃,这样我们就能够看到玻璃后面的物体了。
在我们的计算机图形中,我们可以使用alpha混合来完成透明的效果。而alpha混合是一种将图像和其背景结合起来并且创建出局部透明的外观的处理过程。混合过程就是用的alpha通道。(引用wikipedia.com,answers.com)
Code:transparentrectangles.py
#!/usr/bin/python
# ZetCode PyGTK tutorial
#
# This program shows transparent
# rectangles using cairo
#
# author: jan bodnar
# website: zetcode.com
# last edited: February 2009
import gtk
class PyApp(gtk.Window):
def __init__(self):
super(PyApp, self).__init__()
self.set_title("Transparent rectangles")
self.resize(590, 90)
self.set_position(gtk.WIN_POS_CENTER)
self.connect("destroy", gtk.main_quit)
darea = gtk.DrawingArea()
darea.connect("expose-event", self.expose)
self.add(darea)
self.show_all()
def expose(self, widget, event):
cr = widget.window.cairo_create()
for i in range(1, 11):
cr.set_source_rgba(0, 0, 1, i*0.1)
cr.rectangle(50*i, 20, 40, 40)
cr.fill()
PyApp()
gtk.main()
在例子中,我们用不同透明度水平值来画10个矩形。
cr.set_source_rgba(0, 0, 1, i*0.1)
set_source_rgba()方法的最后一个参数就是alpha透明度。
Figure:Transparent Rectangles
Soulmate
下面的例子,我们将在窗口上画一些文本。
Code:soulmate.py
#!/usr/bin/python
# ZetCode PyGTK tutorial
#
# This program draws text
# using cairo
#
# author: jan bodnar
# website: zetcode.com
# last edited: February 2009
import gtk
import cairo
class PyApp(gtk.Window):
def __init__(self):
super(PyApp, self).__init__()
self.set_title("Soulmate")
self.set_size_request(370, 240)
self.set_position(gtk.WIN_POS_CENTER)
self.connect("destroy", gtk.main_quit)
darea = gtk.DrawingArea()
darea.connect("expose-event", self.expose)
self.add(darea)
self.show_all()
def expose(self, widget, event):
cr = widget.window.cairo_create()
cr.set_source_rgb(0.1, 0.1, 0.1)
cr.select_font_face("Purisa", cairo.FONT_SLANT_NORMAL,
cairo.FONT_WEIGHT_NORMAL)
cr.set_font_size(13)
cr.move_to(20, 30)
cr.show_text("Most relationships seem so transitory")
cr.move_to(20, 60)
cr.show_text("They're all good but not the permanent one")
cr.move_to(20, 120)
cr.show_text("Who doesn't long for someone to hold")
cr.move_to(20, 150)
cr.show_text("Who knows how to love without being told")
cr.move_to(20, 180)
cr.show_text("Somebody tell me why I'm on my own")
cr.move_to(20, 210)
cr.show_text("If there's a soulmate for everyone")
PyApp()
gtk.main()
我们从Natasha Bedingfields Soulmate这首歌显示了部分歌词。
cr.select_font_face("Purisa", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
这里我们指定了我们要使用的字体。
cr.set_font_size(13)
这里我们指定了字体的大小。
cr.move_to(20, 30)
这里我们将点移动到我们要绘制文本的地方。
cr.show_text("Most relationships seem so transitory")
用show_text()方法在窗口上绘制文本。
Figure:Soulmate
在PyGTK编程库的这章中,我们使用Cairo图形库进行绘制工作。