PyGTK FAQ Drawing with cairo

Материал из Wiki.crossplatform.ru

(Различия между версиями)
Перейти к: навигация, поиск
(Новая: In this part of the PyGTK programming tutorial, we will do some drawing with the Cairo library. <b>Cairo</b> is a library for creating 2D vector graphics. We can use it to draw our own ...)
(Удалено по требованию автора...)
 
(1 промежуточная версия не показана)
Строка 1: Строка 1:
-
In this part of the PyGTK programming tutorial, we will do some drawing with the Cairo library.
 
-
<b>Cairo</b> is a library for creating 2D vector graphics. We can use it to draw our own widgets, charts or various effects or animations.
 
-
 
-
== Simple drawing ==
 
-
The stroke operation draws the outlines of shapes and the  fill operation fills the insides of shapes. Next we will demonstrate these two operations.
 
-
<source lang="python">
 
-
#!/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()
 
-
</source>
 
-
 
-
In our example, we will draw a circle and will it with a solid color.
 
-
 
-
<source lang="python">
 
-
darea = gtk.DrawingArea()
 
-
</source>
 
-
 
-
We will be doing our drawing operations on the <b>DrawingArea</b>  widget.
 
-
 
-
<source lang="python">
 
-
darea.connect("expose-event", self.expose)
 
-
 
-
</source>
 
-
 
-
We do all drawing in a method, that is a handler for the <b>expose-event</b> signal.
 
-
 
-
<source lang="python">
 
-
cr = widget.window.cairo_create()
 
-
</source>
 
-
 
-
We create the cairo context object from the <b>gdk.Window</b> of the drawing area. The context is an object that is used to draw on all Drawable objects.
 
-
 
-
<source lang="python">
 
-
cr.set_line_width(9)
 
-
</source>
 
-
 
-
We set the width of the line to 9 pixels.
 
-
 
-
<source lang="python">
 
-
cr.set_source_rgb(0.7, 0.2, 0.0)
 
-
</source>
 
-
 
-
We set the color to dark red.
 
-
 
-
<source lang="python">
 
-
w = self.allocation.width
 
-
h = self.allocation.height
 
-
 
-
cr.translate(w/2, h/2)
 
-
</source>
 
-
 
-
We get the width and height of the drawing area.  We move the origin into the middle of the window.
 
-
 
-
<source lang="python">
 
-
cr.arc(0, 0, 50, 0, 2*math.pi)
 
-
cr.stroke_preserve()
 
-
</source>
 
-
 
-
We draw the outside shape of a circle. In red color. The <b>stroke_preserve()</b>  strokes the current path according to the current line width, line join, line cap, and dash settings. Unlike the <b>stroke()</b>, it preserves the path within the cairo context.
 
-
 
-
<source lang="python">
 
-
cr.set_source_rgb(0.3, 0.4, 0.6)
 
-
cr.fill()
 
-
</source>
 
-
 
-
This fills the interior of the circle with some blue color.
 
-
 
-
[[image: pygtk_faq_simpledrawing.png | center]]
 
-
 
-
== Basic shapes ==
 
-
The next example draws some basic shapes onto the window.
 
-
<source lang="python">
 
-
#!/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()
 
-
</source>
 
-
 
-
In this example, we will create a rectangle, a square, a circle, an arc and an ellipse.
 
-
 
-
<source lang="python">
 
-
cr.rectangle(20, 20, 120, 80)
 
-
cr.rectangle(180, 20, 80, 80)
 
-
cr.fill()
 
-
</source>
 
-
 
-
These lines draw a rectangle and a square.
 
-
 
-
<source lang="python">
 
-
 
-
cr.arc(330, 60, 40, 0, 2*math.pi)
 
-
cr.fill()
 
-
</source>
 
-
 
-
Here the <b>arc()</b> method draws a full circle.
 
-
 
-
<source lang="python">
 
-
cr.scale(1, 0.7)
 
-
cr.arc(0, 0, 50, 0, 2*math.pi)
 
-
cr.fill()
 
-
</source>
 
-
 
-
If we want to draw an oval, we do some scaling first. Here the <b>scale()</b> method shrinks the y axis.
 
-
 
-
[[image: pygtk_faq_basicshapes.png | center]]
 
-
 
-
== Colors ==
 
-
A color is an object representing a combination of Red, Green, and Blue (RGB) intensity values. Cairo valid RGB values are in the range 0 to 1.
 
-
<source lang="python">
 
-
#!/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()
 
-
</source>
 
-
 
-
We draw three rectangles in three different colors.
 
-
 
-
<source lang="python">
 
-
cr.set_source_rgb(0.2, 0.23, 0.9)
 
-
</source>
 
-
 
-
The <b>set_source_rgb()</b> method sets a color for the  cairo context. The three parameters of the method are the color intensity values.
 
-
 
-
<source lang="python">
 
-
cr.rectangle(10, 15, 90, 60)
 
-
cr.fill()
 
-
</source>
 
-
 
-
We create a rectangle shape and fill it with the previously specified color.
 
-
 
-
[[image: pygtk_faq_colors.png | center]]
 
-
 
-
== Transparent rectangles ==
 
-
Transparency is the quality of being able to see through a material. The easiest way to understand  transparency is to imagine a piece of glass or water. Technically, the rays of light can go through the glass and this way we can see objects behind the glass. In computer graphics, we can achieve transparency effects using alpha compositing. Alpha compositing is the process of combining an image with a background to create the appearance of partial transparency. The composition process uses an alpha channel. (wikipedia.org, answers.com)
 
-
<source lang="python">
 
-
#!/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()
 
-
</source>
 
-
 
-
In the example we will draw ten rectangles with different levels of transparency.
 
-
 
-
<source lang="python">
 
-
cr.set_source_rgba(0, 0, 1, i*0.1)
 
-
</source>
 
-
 
-
The last parameter of the <b>set_source_rgba()</b> method is the alpha transparency.
 
-
 
-
[[image: pygtk_faq_transparency.png | center]]
 
-
 
-
== Soulmate ==
 
-
In the next example, we draw some text on the window.
 
-
<source lang="python">
 
-
#!/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()
 
-
</source>
 
-
 
-
We display part of the lyrics from the Natasha Bedingfields Soulmate song.
 
-
 
-
<source lang="python">
 
-
  cr.select_font_face("Purisa", cairo.FONT_SLANT_NORMAL,
 
-
      cairo.FONT_WEIGHT_NORMAL)
 
-
</source>
 
-
 
-
Here we specify the font, that we use.
 
-
 
-
<source lang="python">
 
-
cr.set_font_size(13)
 
-
</source>
 
-
 
-
We specify the size of the font.
 
-
 
-
<source lang="python">
 
-
cr.move_to(20, 30)
 
-
</source>
 
-
 
-
We move to the point, where we will draw the text.
 
-
 
-
<source lang="python">
 
-
cr.show_text("Most relationships seem so transitory")
 
-
</source>
 
-
 
-
The <b>show_text()</b> method draws text onto the window.
 
-
 
-
[[image: pygtk_faq_soulmate.png | center]]
 
-
 
-
In this chapter of the PyGTK programming library, we were drawing with the Cairo graphics library.
 
-
 
-
== Donut ==
 
-
In the following example we create an complex shape by rotating a bunch of ellipses.
 
-
<source lang="python">
 
-
#!/usr/bin/python
 
-
# ZetCode PyGTK tutorial
 
-
#
 
-
# This program creates a donut
 
-
# with 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("Donut")
 
-
        self.set_size_request(350, 250)
 
-
        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(0.5)
 
-
 
-
        w = self.allocation.width
 
-
        h = self.allocation.height
 
-
     
 
-
        cr.translate(w/2, h/2)
 
-
        cr.arc(0, 0, 120, 0, 2*math.pi)
 
-
        cr.stroke()
 
-
       
 
-
 
-
        for i in range(36):
 
-
            cr.save()
 
-
            cr.rotate(i*math.pi/36)
 
-
            cr.scale(0.3, 1)
 
-
            cr.arc(0, 0, 120, 0, 2*math.pi)
 
-
            cr.restore()
 
-
            cr.stroke()
 
-
           
 
-
PyApp()
 
-
gtk.main()
 
-
</source>
 
-
 
-
In this example, we create a donut. The shape resembles a cookie, hence the name donut.
 
-
 
-
<source lang="python">
 
-
cr.translate(w/2, h/2)
 
-
cr.arc(0, 0, 120, 0, 2*math.pi)
 
-
cr.stroke()
 
-
</source>
 
-
 
-
In the beginning there is an ellipse.
 
-
 
-
<source lang="python">
 
-
  for i in range(36):
 
-
      cr.save()
 
-
      cr.rotate(i*math.pi/36)
 
-
      cr.scale(0.3, 1)
 
-
      cr.arc(0, 0, 120, 0, 2*math.pi)
 
-
      cr.restore()
 
-
      cr.stroke()
 
-
</source>
 
-
 
-
After several rotations, there is a donut. We insulate each rotate and scale operations from one another with the <b>save()</b> and <b>restore()</b> methods.
 
-
 
-
[[image: pygtk_faq_donut.jpg | center]]
 
-
 
-
== Gradients ==
 
-
In computer graphics, gradient is a smooth blending of shades from light to dark or from one color to another. In 2D drawing programs and paint programs, gradients are used to create colorful backgrounds and special effects as well as to simulate lights and shadows. (answers.com)
 
-
<source lang="python">
 
-
#!/usr/bin/python
 
-
# ZetCode PyGTK tutorial
 
-
#
 
-
# This program works with
 
-
# gradients in 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("Gradients")
 
-
        self.set_size_request(340, 390)
 
-
        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()
 
-
        lg1 = cairo.LinearGradient(0.0, 0.0, 350.0, 350.0)
 
-
     
 
-
        count = 1
 
-
 
-
        i = 0.1   
 
-
        while i < 1.0:
 
-
            if count % 2:
 
-
                lg1.add_color_stop_rgba(i, 0, 0, 0, 1)
 
-
            else:
 
-
                lg1.add_color_stop_rgba(i, 1, 0, 0, 1)
 
-
            i = i + 0.1
 
-
            count = count + 1     
 
-
 
-
 
-
        cr.rectangle(20, 20, 300, 100)
 
-
        cr.set_source(lg1)
 
-
        cr.fill()
 
-
 
-
        lg2 = cairo.LinearGradient(0.0, 0.0, 350.0, 0)
 
-
     
 
-
        count = 1
 
-
       
 
-
        i = 0.05   
 
-
        while i < 0.95:
 
-
            if count % 2:
 
-
                lg2.add_color_stop_rgba(i, 0, 0, 0, 1)
 
-
            else:
 
-
                lg2.add_color_stop_rgba(i, 0, 0, 1, 1)
 
-
            i = i + 0.025
 
-
            count = count + 1       
 
-
 
-
        cr.rectangle(20, 140, 300, 100)
 
-
        cr.set_source(lg2)
 
-
        cr.fill()
 
-
 
-
        lg3 = cairo.LinearGradient(20.0, 260.0,  20.0, 360.0)
 
-
        lg3.add_color_stop_rgba(0.1, 0, 0, 0, 1)
 
-
        lg3.add_color_stop_rgba(0.5, 1, 1, 0, 1)
 
-
        lg3.add_color_stop_rgba(0.9, 0, 0, 0, 1)
 
-
 
-
        cr.rectangle(20, 260, 300, 100)
 
-
        cr.set_source(lg3)
 
-
        cr.fill()
 
-
 
-
 
-
PyApp()
 
-
gtk.main()
 
-
</source>
 
-
 
-
In our example, we draw three rectangles with three different gradients.
 
-
 
-
<source lang="python">
 
-
lg1 = cairo.LinearGradient(0.0, 0.0, 350.0, 350.0)
 
-
</source>
 
-
 
-
Here we create a linear gradient pattern. The parameters specify the line,  along which we draw the gradient. In our case it is a vertical line.
 
-
 
-
<source lang="python">
 
-
lg3 = cairo.LinearGradient(20.0, 260.0,  20.0, 360.0)
 
-
lg3.add_color_stop_rgba(0.1, 0, 0, 0, 1)
 
-
lg3.add_color_stop_rgba(0.5, 1, 1, 0, 1)
 
-
lg3.add_color_stop_rgba(0.9, 0, 0, 0, 1)
 
-
</source>
 
-
 
-
We define color stops to produce our gradient pattern. In this case, the gradient is a blending of black and yellow colors. By adding two black and one yellow stops, we create a horizontal gradient pattern. What do these stops actually mean? In our case, we begin with black color, which will stop at 1/10 of the size. Then we begin to gradually paint in yellow, which will culminate at the centre of the shape. The yellow color stops at 9/10 of the size, where we begin painting in black again, until the end.
 
-
 
-
[[image: pygtk_faq_gradients.png | center]]
 
-
 
-
== Puff ==
 
-
In the following example, we create a puff effect. The example will display a growing centered text, that will gradually fade out from some point. This is a very common effect, which you can often see in flash animations.
 
-
<source lang="python">
 
-
#!/usr/bin/python
 
-
# ZetCode PyGTK tutorial
 
-
#
 
-
# This program creates a puff
 
-
# effect
 
-
#
 
-
# author: jan bodnar
 
-
# website: zetcode.com
 
-
# last edited: February 2009
 
-
 
-
import gtk
 
-
import glib
 
-
import cairo
 
-
 
-
class PyApp(gtk.Window):
 
-
 
-
    def __init__(self):
 
-
        super(PyApp, self).__init__()
 
-
       
 
-
        self.set_title("Puff")
 
-
        self.resize(350, 200)
 
-
        self.set_position(gtk.WIN_POS_CENTER)
 
-
 
-
        self.connect("destroy", gtk.main_quit)
 
-
 
-
        self.darea = gtk.DrawingArea()
 
-
        self.darea.connect("expose-event", self.expose)
 
-
        self.add(self.darea)
 
-
       
 
-
        self.timer = True
 
-
        self.alpha = 1.0
 
-
        self.size = 1.0
 
-
 
-
        glib.timeout_add(14, self.on_timer)
 
-
       
 
-
        self.show_all()
 
-
       
 
-
    def on_timer(self):
 
-
        if not self.timer: return False
 
-
   
 
-
        self.darea.queue_draw()
 
-
        return True
 
-
 
-
   
 
-
    def expose(self, widget, event):
 
-
 
-
        cr = widget.window.cairo_create()
 
-
 
-
        w = self.allocation.width
 
-
        h = self.allocation.height
 
-
 
-
        cr.set_source_rgb(0.5, 0, 0)
 
-
        cr.paint()
 
-
 
-
        cr.select_font_face("Courier", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_BOLD)
 
-
 
-
        self.size = self.size + 0.8
 
-
 
-
        if self.size > 20:
 
-
            self.alpha = self.alpha - 0.01
 
-
       
 
-
        cr.set_font_size(self.size)
 
-
        cr.set_source_rgb(1, 1, 1)
 
-
       
 
-
        (x, y, width, height, dx, dy) = cr.text_extents("ZetCode")
 
-
 
-
        cr.move_to(w/2 - width/2, h/2)
 
-
        cr.text_path("ZetCode")
 
-
        cr.clip()
 
-
        cr.stroke()
 
-
        cr.paint_with_alpha(self.alpha)
 
-
 
-
        if self.alpha <= 0:
 
-
            self.timer = False
 
-
 
-
PyApp()
 
-
gtk.main()
 
-
</source>
 
-
 
-
The example creates a growing and fading text on the window.
 
-
 
-
<source lang="python">
 
-
glib.timeout_add(14, self.on_timer)
 
-
</source>
 
-
 
-
Every 14 ms the <b>on_timer()</b> method is called. 
 
-
 
-
<source lang="python">
 
-
def on_timer(self):
 
-
    if not self.timer: return False
 
-
 
 
-
    self.darea.queue_draw()
 
-
    return True   
 
-
</source>
 
-
 
-
In the <b>on_timer()</b> method, we call  the <b>queue_draw()</b> method upon the drawing area, which triggers the expose signal.
 
-
 
-
<source lang="python">
 
-
cr.set_source_rgb(0.5, 0, 0)
 
-
cr.paint()
 
-
</source>
 
-
 
-
We set the background color to dark red color.
 
-
 
-
<source lang="python">
 
-
self.size = self.size + 0.8
 
-
</source>
 
-
 
-
Each cycle, the font size will grow by 0.8 units.
 
-
 
-
<source lang="python">
 
-
if self.size > 20:
 
-
    self.alpha = self.alpha - 0.01
 
-
</source>
 
-
 
-
The fading out begins after the font size is bigger than 20.
 
-
 
-
<source lang="python">
 
-
(x, y, width, height, dx, dy) = cr.text_extents("ZetCode")
 
-
</source>
 
-
 
-
We get the text metrics.
 
-
 
-
<source lang="python">
 
-
cr.move_to(w/2 - width/2, h/2)
 
-
 
-
</source>
 
-
 
-
We use the text metrics to center the text on the window.
 
-
 
-
<source lang="python">
 
-
cr.text_path("ZetCode")
 
-
cr.clip()
 
-
</source>
 
-
 
-
We get the path of the text and set the current clip region to it.
 
-
 
-
<source lang="python">
 
-
cr.stroke()
 
-
cr.paint_with_alpha(self.alpha)
 
-
 
-
</source>
 
-
 
-
We paint the current path and take alpha value into account.
 
-
 
-
[[image: pygtk_faq_puff.gif | center]]
 
-
 
-
== Reflection ==
 
-
In the next example we show a reflected image. This beautiful effect makes an  illusion as if the image was reflected in water.
 
-
<source lang="python">
 
-
#!/usr/bin/python
 
-
# ZetCode PyGTK tutorial
 
-
#
 
-
# This program creates an
 
-
# image reflection
 
-
#
 
-
# author: jan bodnar
 
-
# website: zetcode.com
 
-
# last edited: February 2009
 
-
 
-
import gtk
 
-
import cairo
 
-
import sys
 
-
 
-
class PyApp(gtk.Window):
 
-
 
-
    def __init__(self):
 
-
        super(PyApp, self).__init__()
 
-
       
 
-
        self.set_title("Reflection")
 
-
        self.resize(300, 350)
 
-
        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)
 
-
       
 
-
        try:
 
-
            self.surface = cairo.ImageSurface.create_from_png("slanec.png")
 
-
        except Exception, e:
 
-
            print e.message
 
-
            sys.exit(1)
 
-
       
 
-
       
 
-
        self.imageWidth = self.surface.get_width()
 
-
        self.imageHeight = self.surface.get_height()
 
-
        self.gap = 40
 
-
        self.border = 20
 
-
 
-
        self.show_all()
 
-
   
 
-
    def expose(self, widget, event):
 
-
 
-
        cr = widget.window.cairo_create()
 
-
 
-
                 
 
-
        w = self.allocation.width
 
-
        h = self.allocation.height
 
-
         
 
-
        lg = cairo.LinearGradient(w/2, 0, w/2, h*3)
 
-
        lg.add_color_stop_rgba(0, 0, 0, 0, 1)
 
-
        lg.add_color_stop_rgba(h, 0.2, 0.2, 0.2, 1)
 
-
 
-
        cr.set_source(lg)
 
-
        cr.paint()
 
-
       
 
-
        cr.set_source_surface(self.surface, self.border, self.border)
 
-
        cr.paint()
 
-
 
-
        alpha = 0.7
 
-
        step = 1.0 / self.imageHeight
 
-
     
 
-
        cr.translate(0, 2 * self.imageHeight + self.gap)
 
-
        cr.scale(1, -1)
 
-
       
 
-
        i = 0
 
-
       
 
-
     
 
-
        while(i < self.imageHeight):
 
-
            cr.rectangle(self.border, self.imageHeight-i, self.imageWidth, 1)
 
-
 
-
            i = i + 1
 
-
           
 
-
            cr.clip()
 
-
            cr.set_source_surface(self.surface, self.border, self.border)
 
-
            alpha = alpha - step
 
-
            cr.paint_with_alpha(alpha)
 
-
            cr.reset_clip()
 
-
       
 
-
 
-
PyApp()
 
-
gtk.main()
 
-
</source>
 
-
 
-
The example shows a reflected castle.
 
-
 
-
<source lang="python">
 
-
lg = cairo.LinearGradient(w/2, 0, w/2, h*3)
 
-
lg.add_color_stop_rgba(0, 0, 0, 0, 1)
 
-
lg.add_color_stop_rgba(h, 0.2, 0.2, 0.2, 1)
 
-
 
-
cr.set_source(lg)
 
-
cr.paint()
 
-
 
-
</source>
 
-
 
-
The background is filled with a gradiet paint. The paint is a smooth blending from black to dark gray.
 
-
 
-
<source lang="python">
 
-
cr.translate(0, 2 * self.imageHeight + self.gap)
 
-
cr.scale(1, -1)
 
-
</source>
 
-
 
-
This code flips the image and translates it below the original image. The translation operation is necessary, because the scaling operation makes the image upside down and translates the image up. To understand what happens, simply take a photograph and place it on the table. Now flip it.
 
-
 
-
<source lang="python">
 
-
cr.rectangle(self.border, self.imageHeight-i, self.imageWidth, 1)
 
-
 
-
i = i + 1
 
-
           
 
-
cr.clip()
 
-
cr.set_source_surface(self.surface, self.border, self.border)
 
-
alpha = alpha - step
 
-
cr.paint_with_alpha(alpha)
 
-
cr.reset_clip()
 
-
 
-
</source>
 
-
 
-
Crucial part of the code. We make the second image transparent. But the transparency is not constant. The image gradually fades out. This is achieved with the gradient.
 
-
 
-
[[image: pygtk_faq_reflection.png | center]]
 
-
 
-
== Waiting ==
 
-
In this examle, we use transparency effect to create a waiting demo. We will draw 8 lines that will gradually fade out creating an illusion, that a line is moving. Such effects are often used to inform users, that a lengthy task is going on behind the scenes. An example is streaming video over the internet. 
 
-
<source lang="python">
 
-
#!/usr/bin/python
 
-
# ZetCode PyGTK tutorial
 
-
#
 
-
# This program creates an
 
-
# waiting effect
 
-
#
 
-
# author: jan bodnar
 
-
# website: zetcode.com
 
-
# last edited: February 2009
 
-
 
-
import gtk
 
-
import glib
 
-
import math
 
-
import cairo
 
-
 
-
trs = (
 
-
    ( 0.0, 0.15, 0.30, 0.5, 0.65, 0.80, 0.9, 1.0 ),
 
-
    ( 1.0, 0.0,  0.15, 0.30, 0.5, 0.65, 0.8, 0.9 ),
 
-
    ( 0.9, 1.0,  0.0,  0.15, 0.3, 0.5, 0.65, 0.8 ),
 
-
    ( 0.8, 0.9,  1.0,  0.0,  0.15, 0.3, 0.5, 0.65 ),
 
-
    ( 0.65, 0.8, 0.9,  1.0,  0.0,  0.15, 0.3, 0.5 ),
 
-
    ( 0.5, 0.65, 0.8, 0.9, 1.0,  0.0,  0.15, 0.3 ),
 
-
    ( 0.3, 0.5, 0.65, 0.8, 0.9, 1.0,  0.0,  0.15 ),
 
-
    ( 0.15, 0.3, 0.5, 0.65, 0.8, 0.9, 1.0,  0.0, )
 
-
)
 
-
 
-
class PyApp(gtk.Window):
 
-
 
-
    def __init__(self):
 
-
        super(PyApp, self).__init__()
 
-
       
 
-
        self.set_title("Waiting")
 
-
        self.set_size_request(250, 150)
 
-
        self.set_position(gtk.WIN_POS_CENTER)
 
-
 
-
        self.connect("destroy", gtk.main_quit)
 
-
 
-
        self.darea = gtk.DrawingArea()
 
-
        self.darea.connect("expose-event", self.expose)
 
-
        self.add(self.darea)
 
-
       
 
-
        self.count = 0
 
-
       
 
-
        glib.timeout_add(100, self.on_timer)
 
-
       
 
-
        self.show_all()
 
-
       
 
-
    def on_timer(self):
 
-
        self.count = self.count + 1
 
-
        self.darea.queue_draw()
 
-
        return True
 
-
 
-
   
 
-
    def expose(self, widget, event):
 
-
 
-
        cr = widget.window.cairo_create()
 
-
 
-
        cr.set_line_width(3)
 
-
        cr.set_line_cap(cairo.LINE_CAP_ROUND)
 
-
 
-
        w = self.allocation.width
 
-
        h = self.allocation.height
 
-
     
 
-
        cr.translate(w/2, h/2)
 
-
 
-
        for i in range(8):
 
-
            cr.set_source_rgba(0, 0, 0, trs[self.count%8][i])
 
-
            cr.move_to(0.0, -10.0)
 
-
            cr.line_to(0.0, -40.0)
 
-
            cr.rotate(math.pi/4)
 
-
            cr.stroke()
 
-
 
-
 
-
PyApp()
 
-
gtk.main()
 
-
</source>
 
-
 
-
We draw eight lines with eight different alpha values.
 
-
 
-
<source lang="python">
 
-
glib.timeout_add(100, self.on_timer)
 
-
</source>
 
-
 
-
We use a timer function to create animation.
 
-
 
-
<source lang="python">
 
-
trs = (
 
-
    ( 0.0, 0.15, 0.30, 0.5, 0.65, 0.80, 0.9, 1.0 ),
 
-
    ...
 
-
)
 
-
 
-
</source>
 
-
 
-
This is a two dimensional tuple of transparency values used in this demo. There are 8 rows, each for one state. Each of the 8 lines will continuosly use these values.
 
-
 
-
<source lang="python">
 
-
cr.set_line_width(3)
 
-
cr.set_line_cap(cairo.LINE_CAP_ROUND)
 
-
 
-
</source>
 
-
 
-
We make the lines a bit thicker, so that they are better visible. We draw the lines with rouded caps. They look then better.
 
-
 
-
<source lang="python">
 
-
cr.set_source_rgba(0, 0, 0, trs[self.count%8][i]
 
-
</source>
 
-
 
-
Here we define the transparency value for a line.
 
-
 
-
<source lang="python">
 
-
 
-
cr.move_to(0.0, -10.0)
 
-
cr.line_to(0.0, -40.0)
 
-
cr.rotate(math.pi/4)
 
-
cr.stroke()
 
-
</source>
 
-
 
-
These code lines will draw each of the eight lines.
 
-
 
-
[[image: pygtk_faq_waiting.png | center]]
 
-
 
-
In this chapter of the PyGTK programming library, we did some more advanced drawing with the Cairo library.
 
-
 
-
[[Категория:Python]]
 
-
[[Категория:GTK]]
 

Текущая версия на 11:25, 7 апреля 2009