返回介绍

Custom widget in Ruby GTK

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

Toolkits usually provide only the most common widgets like buttons, text widgets, sliders etc. No toolkit can provide all possible widgets. Programmers must create such widgets by themselves. They do it by using the drawing tools provided by the toolkit. There are two possibilities: a programmer can modify or enhance an existing widget or he can create a custom widget from scratch.

Burning widget

This is an example of a widget that we create from scratch. This widget can be found in various media burning applications, like K3B.

custom.rb

#!/usr/bin/ruby

'''
ZetCode Ruby GTK tutorial

This example creates a custom widget.

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

require 'gtk3'

class Burning < Gtk::DrawingArea

  def initialize parent
    @parent = parent

    super()
 
    @num = [ "75", "150", "225", "300", 
      "375", "450", "525", "600", "675" ]
 
    set_size_request 1, 30
    signal_connect "draw" do
      on_draw
    end
  end
  

  def on_draw
  
    cr = window.create_cairo_context
    draw_widget cr
  end
  
  def draw_widget cr
 
    cr.set_line_width 0.8

    cr.select_font_face "Courier", 
      Cairo::FONT_SLANT_NORMAL, Cairo::FONT_WEIGHT_NORMAL
    cr.set_font_size 11

    width = allocation.width
   
    @cur_width = @parent.get_cur_value

    step = (width / 10.0).round

    till = (width / 750.0) * @cur_width
    full = (width / 750.0) * 700

    if @cur_width >= 700
      
      cr.set_source_rgb 1.0, 1.0, 0.72
      cr.rectangle 0, 0, full, 30
      cr.clip
      cr.paint
      cr.reset_clip
      
      cr.set_source_rgb 1.0, 0.68, 0.68
      cr.rectangle full, 0, till-full, 30
      cr.clip
      cr.paint
      cr.reset_clip

    else
      cr.set_source_rgb 1.0, 1.0, 0.72
      cr.rectangle 0, 0, till, 30
      cr.clip
      cr.paint
      cr.reset_clip
    end
     

    cr.set_source_rgb(0.35, 0.31, 0.24)
    
    for i in 1..@num.length
      cr.move_to i*step, 0
      cr.line_to i*step, 5
      cr.stroke
      
      te = cr.text_extents @num[i-1]
      cr.move_to i*step-te.width/2, 15
      cr.text_path @num[i-1]
      cr.stroke
    end     
  end
end
    
 
class RubyApp < Gtk::Window

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

    set_size_request 350, 200    
    set_window_position :center
    
    @cur_value = 0
     
    vbox = Gtk::Box.new :vertical, 2

    scale = Gtk::Scale.new :horizontal
    scale.set_range 0, 750
    scale.set_digits 0
    scale.set_size_request 160, 35
    scale.set_value @cur_value
    
    scale.signal_connect "value-changed" do |w|
      on_changed w
    end
        
    fix = Gtk::Fixed.new
    fix.put scale, 50, 50
    
    vbox.pack_start fix
    
    @burning = Burning.new self
    vbox.pack_start @burning, :expand => false, 
      :fill => false, :padding => 0

    add vbox
    show_all
  end  
    
  def on_changed widget
  
    @cur_value = widget.value
    @burning.queue_draw
  end
  
  def get_cur_value
    return @cur_value
  end
end
  
Gtk.init
  window = RubyApp.new
Gtk.main

We put a Gtk::DrawingArea on the bottom of the window and draw the entire widget manually. All the important code resides in the draw_widget which is called from the on_draw method of the Burning class. This widget shows graphically the total capacity of a medium and the available free space. The widget is controlled by a scale widget. The minimum value of our custom widget is 0, the maximum is 750. If we reach value 700, we began drawing in red colour. This normally indicates overburning.

@num = [ "75", "150", "225", "300", 
  "375", "450", "525", "600", "675" ]

These numbers are shown on the burning widget. They show the capacity of the medium.

@cur_width = @parent.get_cur_value

From the parent widget, we get the current value of the scale widget.

till = (width / 750.0) * @cur_width
full = (width / 750.0) * 700

We use the width variable to do the transformations between the values of the scale and the custom widget's measures. Note that we use floating point values—we get greater precision in drawing. The till parameter determines the total size to be drawn. This value comes from the slider widget. It is a proportion of the whole area. The full parameter determines the point where we begin to draw in red colour.

cr.set_source_rgb 1.0, 1.0, 0.72
cr.rectangle 0, 0, till, 30
cr.clip
cr.paint
cr.reset_clip

We draw a yellow rectangle up to point where the medium is full.

te = cr.text_extents @num[i-1]
cr.move_to i*step-te.width/2, 15
cr.text_path @num[i-1]
cr.stroke

This code here draws the numbers on the burning widget. We calculate the text extents to position the text correctly.

def on_changed widget

  @cur_value = widget.value
  @burning.queue_draw
end

We get the value from the scale widget and store it in the @cur_value variable for later use. We redraw the burning widget.

Burning widget
Figure: Burning widget

In this chapter, we created a custom widget in GTK and Ruby programming language.

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

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

发布评论

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