[翻譯]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指南的這一章中,咱們作了一些基本的繪圖。

相關文章
相關標籤/搜索