返回介绍

Painting with Cairo in Ruby GTK

发布于 2025-02-22 22:19:42 字数 11422 浏览 0 评论 0 收藏 0

In this part of the Ruby GTK tutorial, we will do some painting with the Cairo library.

Cairo is a library for creating 2D vector graphics. We can use it to draw our own widgets, charts or various effects and animations.

Colours

In the first example, we will work with colours. A colour 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.

#!/usr/bin/ruby

'''
ZetCode Ruby GTK tutorial

This program draws tree rectangles filled
with different colours.

Author: Jan Bodnar
Website: www.zetcode.com
Last modified: May 2014
'''

require 'gtk3'


class RubyApp < Gtk::Window

  def initialize
    super
  
    set_title "Colours"
    signal_connect "destroy" do 
      Gtk.main_quit 
    end
    
    init_ui

    set_default_size 360, 100
    set_window_position :center
    show_all
  end
  
  def init_ui
  
    @darea = Gtk::DrawingArea.new  

    @darea.signal_connect "draw" do  
      on_draw
    end
  
    add @darea
  end
  
  def on_draw
  
    cr = @darea.window.create_cairo_context  
    draw_colors cr
  end 
  
  def draw_colors cr
    
    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
  end
end

Gtk.init
  window = RubyApp.new
Gtk.main

In our example, we will draw three rectangles and fill them with three different colours.

@darea = Gtk::DrawingArea.new 

We will be doing our drawing operations on the Gtk::DrawingArea widget.

@darea.signal_connect "draw" do  
  on_draw
end

When the window needs to be redrawn, the draw signal is triggered. In response to this signal, we call the on_draw method.

cr = @darea.window.create_cairo_context  

We create the cairo context object from the Gdk::Window of the drawing area. The context is an object onto which we do all our drawings.

draw_colors cr

The actual drawing is delegated to the draw_colors method. We pass in the cairo context.

cr.set_source_rgb 0.2, 0.23, 0.9

The set_source_rgb method sets a colour for the cairo context. The three parameters of the method are the colour intensity values.

cr.rectangle 10, 15, 90, 60

We draw a rectangle. The first two parameters are the x, y coordinates of the top left corner of the rectangle. The last two parameters are the width and the height of the rectangle.

cr.fill

We fill the inside of the rectangle with the current colour.

Colours
Figure: Colours

Basic shapes

The next example draws some basic shapes onto the window.

#!/usr/bin/ruby

'''
ZetCode Ruby GTK tutorial

This code example draws basic shapes.

Author: Jan Bodnar
Website: www.zetcode.com
Last modified: May 2014
'''

require 'gtk3'


class RubyApp < Gtk::Window

  def initialize
    super
  
    set_title "Basic shapes"
    signal_connect "destroy" do 
      Gtk.main_quit 
    end
    
    init_ui

    set_default_size 390, 240
    set_window_position :center
    
    show_all
  end
  
  def init_ui
  
    @darea = Gtk::DrawingArea.new  
    
    @darea.signal_connect "draw" do  
      on_draw
    end
  
    add @darea
  end
  
  def on_draw
  
    cr = @darea.window.create_cairo_context  
    draw_shapes cr
  end
  
  def draw_shapes cr
  
    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
  end
end

Gtk.init
  window = RubyApp.new
Gtk.main

In this example, we will create a rectangle, a square, a circle, an arc, and an ellipse. We draw outlines in blue colour, insides in white.

cr.rectangle 20, 20, 120, 80
cr.rectangle 180, 20, 80, 80
cr.fill

These lines draw a rectangle and a square.

cr.arc 330, 60, 40, 0, 2*Math::PI
cr.fill

Here the arc method draws a full circle.

cr.translate 220, 180
cr.scale 1, 0.7
cr.arc 0, 0, 50, 0, 2*Math::PI
cr.fill

The translate method moves the object to a specific point. If we want to draw an oval, we do some scaling first. Here the scale method shrinks the y axis.

Basic shapes
Figure: Basic shapes

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)

#!/usr/bin/ruby

'''
ZetCode Ruby GTK tutorial

This program shows transparent rectangles.

Author: Jan Bodnar
Website: www.zetcode.com
Last modified: May 2014
'''

require 'gtk3'


class RubyApp < Gtk::Window

  def initialize
    super
  
    set_title "Transparent rectangles"
    signal_connect "destroy" do 
      Gtk.main_quit 
    end
    
    init_ui

    set_default_size 590, 90
    set_window_position :center
    
    show_all
  end
  
  def init_ui
  
    @darea = Gtk::DrawingArea.new  
    
    @darea.signal_connect "draw" do  
      on_draw
    end
  
    add @darea
  end
  
  def on_draw
    
    cr = @darea.window.create_cairo_context  
    draw_rectangles cr    
  end
  
  def draw_rectangles cr
  
    for i in 1..10
      cr.set_source_rgba 0, 0, 1, i*0.1
      cr.rectangle 50*i, 20, 40, 40
      cr.fill
    end  
  end 
end

Gtk.init
  window = RubyApp.new
Gtk.main

In the example we will draw ten rectangles with different levels of transparency.

cr.set_source_rgba 0, 0, 1, i*0.1

The last parameter of the set_source_rgba method is the alpha transparency.

Transparent rectangles
Figure: Transparent rectangles

Donut

In the following example we create a complex shape by rotating a bunch of ellipses.

#!/usr/bin/ruby

'''
ZetCode Ruby GTK tutorial

This program draws a donut shape.

Author: Jan Bodnar
Website: www.zetcode.com
Last modified: May 2014
'''

require 'gtk3'


class RubyApp < Gtk::Window

  def initialize
    super
  
    set_title "Donut"
    signal_connect "destroy" do 
      Gtk.main_quit 
    end
    
    init_ui

    set_default_size 350, 250
    set_window_position :center
    
    show_all
  end
  
  def init_ui
  
    @darea = Gtk::DrawingArea.new  
    
    @darea.signal_connect "draw" do  
      on_draw
    end
  
    add @darea
  end
  
  def on_draw
  
    cr = @darea.window.create_cairo_context  
    draw_donut cr
  end
  
  def draw_donut cr
  
    cr.set_line_width 0.5

    w = allocation.width
    h = allocation.height
     
    cr.translate w/2, h/2
    cr.arc 0, 0, 120, 0, 2*Math::PI
    cr.stroke
     
    for i in 1..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
    end
  end
end

Gtk.init
  window = RubyApp.new
Gtk.main

In this example, we create a donut. The shape resembles a cookie, hence the name donut.

cr.translate w/2, h/2

The user space origin is moved to the center of the window. The circle and all other ellipses will have their center point located here.

cr.translate w/2, h/2
cr.arc 0, 0, 120, 0, 2*Math::PI
cr.stroke

This is the outer ellipse. Inside this ellipse, we draw all other ellipses.

for i in 1..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
end

We create 36 ellipses along the path of our bounding circle. We insulate each rotate and scale operation from one another with the save() and restore() methods.

Donut
Figure: Donut

Drawing text

In the next example, we draw some text on the window.

#!/usr/bin/ruby

'''
ZetCode Ruby GTK tutorial

This program draws text.

Author: Jan Bodnar
Website: www.zetcode.com
Last modified: May 2014
'''

require 'gtk3'


class RubyApp < Gtk::Window

  def initialize
    super
  
    set_title "Soulmate"
    signal_connect "destroy" do 
      Gtk.main_quit 
    end
    
    init_ui

    set_default_size 370, 240
    set_window_position :center
    
    show_all
  end
  
  def init_ui
  
    @darea = Gtk::DrawingArea.new  
    
    @darea.signal_connect "draw" do  
      on_draw
    end
  
    add @darea 
  end
  
  def on_draw
  
    cr = @darea.window.create_cairo_context  
    draw_lyrics cr
  end
  
  def draw_lyrics cr
  
    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"
  end
end

Gtk.init
  window = RubyApp.new
Gtk.main

We display a part of the lyrics from the Natasha Bedingfield's Soulmate song.

cr.select_font_face "Purisa", Cairo::FONT_SLANT_NORMAL, 
  Cairo::FONT_WEIGHT_NORMAL

Here we specify the font that we use: Purisa normal.

cr.set_font_size 13 

The set_font_size method specifies the size of the font.

cr.move_to 20, 30

We move to the point where we will draw the text.

cr.show_text "Most relationships seem so transitory"

The show_text method draws text on the window.

Soulmate
Figure: Soulmate

In this chapter of the Ruby GTK tutorial, we were painting with Cairo library.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文