[翻译]PyCairo指南--基本绘图

PyCairo中的基本绘图

在PyCairo指南中的这个部分,咱们将会绘制一些基本的元素。咱们将绘制简单的直线,应用填充和stroke操做,咱们将会讨论虚线,线帽和线的交合。 python

直线

直线是很是基本的向量对象。为了绘制一条直线,咱们使用两个方法调用。一个是move_to()调用,咱们须要把起点位置传给它。另外一个是line_to(),咱们则须要把直线的终点传给它。 web

#!/usr/bin/python
'''
ZetCode PyCairo tutorial

In this program, we connect all mouse
clicks with a line.

author: Jan Bodnar
website: zetcode.com
last edited: August 2012
'''

import gtk
import cairo

class MouseButtons:
    LEFT_BUTTON = 1
    RIGHT_BUTTON = 3

class MainWindow(gtk.Window):
    def __init__(self):
        super(self.__class__, self).__init__()
        self.init_ui()
        print "MainWindow: " + str(self)
        
    def init_ui(self):
        self.darea = gtk.DrawingArea()
        self.darea.connect("expose_event", self.expose)
        self.darea.set_events(gtk.gdk.BUTTON_PRESS_MASK 
                              | gtk.gdk.BUTTON_RELEASE_MASK)
        self.add(self.darea)
        
        self.coords = []
        
        self.darea.connect("button-press-event", self.on_button_press)

        self.set_title("Lines")
        self.resize(300, 200)
        self.set_position(gtk.WIN_POS_CENTER)
        
        self.connect("delete-event", gtk.main_quit)
        self.show_all()
        
    def on_button_press(self, widget, event):
        if event.type == gtk.gdk.BUTTON_PRESS and event.button == MouseButtons.LEFT_BUTTON:
            self.coords.append([event.x, event.y])
        if event.type == gtk.gdk.BUTTON_PRESS and event.button == MouseButtons.RIGHT_BUTTON:
            self.darea.queue_draw()
        pass
        
    def expose(self, widget, event):
        self.context = widget.window.cairo_create()
        self.on_draw(300, self.context)
        
    def on_draw(self, wid, cr):
        cr.set_source_rgb(0, 0, 0)
        cr.set_line_width(0.5)
        
        for i in self.coords:
            for j in self.coords:
                cr.move_to (i[0], i[1])
                cr.line_to (j[0], j[1])
                cr.stroke()
        del self.coords[:]
        
def main():
    window = MainWindow()

    gtk.main()
        
if __name__ == "__main__":
    main()

在咱们的例子中,咱们用鼠标左键随机的在窗口中点。每一次点击的位置都会被存进一个列表。当咱们在窗口中按下鼠标右键时,列表中每个点都会与其余全部的点链接起来。经过这种方式,咱们能够建立一些有趣的对象。再次点击鼠标右键能够清空窗口,咱们就能够建立另外一个对象了。 app

class MouseButtons:
    LEFT_BUTTON = 1
    RIGHT_BUTTON = 3

GTK文档简单的状态标记,鼠标左键为数字1,鼠标右键为数字3。咱们建立一个定制的类来为鼠标的键作标识。 ui

self.darea.set_events(gtk.gdk.BUTTON_PRESS_MASK 
                              | gtk.gdk.BUTTON_RELEASE_MASK)

某些事件默认状况下是不打开的。鼠标按钮按下事件即属其中。然而,咱们须要打开鼠标按钮按下事件。 this

self.darea.connect("button-press-event", self.on_button_press)

在这个例子中,咱们对鼠标按下事件做出反应。 spa

cr.set_source_rgb(0, 0, 0)
        cr.set_line_width(0.5)

将用黑色墨水和0.5点宽度来画直线。 code

for i in self.coords:
            for j in self.coords:
                cr.move_to (i[0], i[1])
                cr.line_to (j[0], j[1])
                cr.stroke()

咱们把列表中每个点链接到其余的每个点。stroke()调用绘制直线。 对象

del self.coords[:]

最后,全部的坐标被删除。如今咱们能够建立另外一个对象了。 事件

def on_button_press(self, widget, event):
        if event.type == gtk.gdk.BUTTON_PRESS and event.button == MouseButtons.LEFT_BUTTON:
            self.coords.append([event.x, event.y])

若是按下了鼠标左按钮,咱们会把它的x,y坐标添加到self.coords列表中去。 ci

if event.type == gtk.gdk.BUTTON_PRESS and event.button == MouseButtons.RIGHT_BUTTON:
            self.darea.queue_draw()

按下鼠标右键时,咱们调用queue_draw()方法,它将会渲染绘制区域。全部的点会连成线。


Figure: Lines

填充和stroke

stroke操做绘制形状的轮廓,而填充操做则填充形状的内部。

#!/usr/bin/python
'''
ZetCode PyCairo tutorial

This code example draws a circle
using the PyCairo library

author: Jan Bodnar
website: zetcode.com
last edited: August 2012
'''

import cairo
import gtk
import math

class MainWindow(gtk.Window):
    def __init__(self):
        super(self.__class__, self).__init__()
        self.init_ui()

    def init_ui(self):
        self.darea = gtk.DrawingArea()
        self.darea.connect("expose_event", self.expose)
        self.add(self.darea)

        self.set_title("Fill & stroke")
        self.resize(230, 150)
        self.set_position(gtk.WIN_POS_CENTER)
        
        self.connect("delete-event", gtk.main_quit)
        self.show_all()

    def expose(self, widget, event):
        self.context = widget.window.cairo_create()
        self.on_draw(230, self.context)
        
    def on_draw(self, wid, cr):
        cr.set_line_width(9)
        cr.set_source_rgb(0.7, 0.2, 0.0)
        
        width, height = self.get_size()
        
        cr.translate(width/2, height/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()
        
def main():
    window = MainWindow()

    gtk.main()
        
if __name__ == "__main__":
    main()

在咱们的例子中,咱们将画一个圆圈,而后用一种颜色填充它。

import math

pi常量须要这个模块,后面在绘制圆圈时会用到pi。

cr.set_line_width(9)
        cr.set_source_rgb(0.7, 0.2, 0.0)

咱们用set_line_width()方法设置线的宽度。咱们使用set_source_rgb()把source设为某种暗红色。

width, height = self.get_size()

此处咱们获取窗口的宽度和高度。咱们须要这些值来将圆圈放到窗口的中心位置。

cr.translate(width/2, height/2)
        cr.arc(0, 0, 50, 0, 2 * math.pi)
        cr.stroke_preserve()

经过translate()方法,咱们将绘制的原点移动到窗口的中心位置。咱们想要将咱们的圆圈放在中心位置。arc()方法向cairo绘制上下文中添加一个新的圆圈的path。最后,stroke_preserve()方法绘制圆圈的轮廓。不像stroke()方法,它会保留形状以用于后面的绘制。

cr.set_source_rgb(0.3, 0.4, 0.6)
        cr.fill()

咱们换一种颜色来画,使用fill()方法并用一种新的颜色来填充圆圈。


Figure: Fill & stroke

Pen dashes

每一条直线均可以用不一样的pen dash来画。一个pen dash定义了直线的style。dash模式由set_dash()方法指定。模式由一个浮点值组成的dash列表来描述。它们设置了dash模式的on和off部分。dash被stroke()方法用来建立一条直线。若是dashes的数量为0,则dashing是被关掉的。若是dashes的数量为1,则假设是一个对称的模式,其中on和off部分交替出现,它们的大小由dashes中的那个值来指定。

def on_draw(self, wid, cr):
        cr.set_source_rgba(0, 0, 0, 1)
        cr.set_line_width(2)
        
        cr.set_dash([4.0, 21.0, 2.0])
        cr.move_to(40, 30)
        cr.line_to(250, 30)
        cr.stroke()
        
        cr.set_dash([14.0, 6.0])
        cr.move_to(40, 50)
        cr.line_to(250, 50)
        cr.stroke()
        
        cr.set_dash([1.0])
        cr.move_to(40, 70)
        cr.line_to(250, 70)
        cr.stroke()

咱们用三种不一样类型的pen dashes画了三条直线。

cr.set_dash([4.0, 21.0, 2.0])

咱们定义了具备三个数字的模式。咱们画4个点,21个不画,而后2个点画。接下来是4个点不画,21个点画和2个点不画。这个模式如此交替,直到直线的终点。

cr.set_dash([14.0, 6.0])

在这个模式中,咱们老是让14个点画,6个不画。

cr.set_dash([1.0])

咱们在这儿建立了一个对称的pen dash模式,交替的一个点画,一个点不画。


Figure: Pen dashes

Line caps

Line caps 是直线的终点。

  • cairo.LINE_CAP_BUTT
  • cairo.LINE_CAP_ROUND
  • cairo.LINE_CAP_SQUARE

Cairo中有三种不一样的line cap style。

Figure: Square, round and butt caps

相对于具备一个cairo.LINE_CAP_BUTT cap的直线,具备一个cairo.LINE_CAP_SQUARE cap的直线将有不同的大小。若是一条直线x单元宽,具备一个cairo.LINE_CAP_SQUARE cap的直线将会要大整整x个单元。开始处x/2个单元,结尾处x/2个单元。

def on_draw(self, wid, cr):
        cr.set_source_rgba(0, 0, 0, 1)
        cr.set_line_width(12)
        
        cr.set_line_cap(cairo.LINE_CAP_BUTT)
        cr.move_to(30, 50)
        cr.line_to(150, 50)
        cr.stroke()
        
        cr.set_line_cap(cairo.LINE_CAP_ROUND)
        cr.move_to(30, 90)
        cr.line_to(150, 90)
        cr.stroke()
        
        cr.set_line_cap(cairo.LINE_CAP_SQUARE)
        cr.move_to(30, 130)
        cr.line_to(150, 130)
        cr.stroke()
        
        cr.set_line_width(1.5)
        
        cr.move_to(30, 35)
        cr.line_to(30, 145)
        cr.stroke()
        
        cr.move_to(150, 35)
        cr.line_to(150, 145)
        cr.stroke()
        
        cr.move_to(155, 35)
        cr.line_to(155, 145)
        cr.stroke()

这个例子画了三条具备不一样的line caps的直线。它也经过画三条额外的垂直方向的细线生动的演示了直线不一样大小的影响。

cr.set_line_width(12)

咱们的直线将是12个单元宽的。默认的直线宽度为2.

cr.set_line_cap(cairo.LINE_CAP_ROUND)
        cr.move_to(30, 90)
        cr.line_to(150, 90)
        cr.stroke()

此处咱们画了一条具备一个cairo.LINE_CAP_ROUND cap的水平直线。

cr.set_line_width(1.5)
        
        cr.move_to(30, 35)
        cr.line_to(30, 145)
        cr.stroke()

这是用于演示不一样直线大小的影响的三条垂直直线之一。


Figure: Line caps

Line joins

直线能够用三种不一样的联合style来作联合。

  • cairo.LINE_JOIN_MITER
  • cairo.LINE_JOIN_BEVEL
  • cairo.LINE_JOIN_ROUND

Figure: Bevel, Round, Miter line joins

def on_draw(self, wid, cr):
        cr.set_line_width(14)
        
        cr.rectangle(30, 30, 100, 100)
        cr.set_line_join(cairo.LINE_JOIN_MITER)
        cr.stroke()
        
        cr.rectangle(160, 30, 100, 100)
        cr.set_line_join(cairo.LINE_JOIN_BEVEL)
        cr.stroke()
        
        cr.rectangle(100, 160, 100, 100)
        cr.set_line_join(cairo.LINE_JOIN_ROUND)
        cr.stroke()

在这个例子中,咱们画了三个具备不一样的线联合的厚矩形。

cr.set_line_width(14)

直线是14个单元宽的。

cr.rectangle(30, 30, 100, 100)
        cr.set_line_join(cairo.LINE_JOIN_MITER)
        cr.stroke()

此处咱们画了一个有着 cairo.LINE_JOIN_MITER联合风格的矩形。


Figure: Line joins

PyCairo指南的这一章中,咱们作了一些基本的绘图。

相关文章
相关标签/搜索