原文: http://zetcode.com/gui/rubygtk/customwidget/

工具箱通常仅提供最常见的窗口小部件,例如按钮,文本窗口小部件,滑块等。没有工具箱可以提供所有可能的窗口小部件。 程序员必须自己创建此类小部件。 他们使用工具箱提供的绘图工具来完成此任务。 有两种可能:程序员可以修改或增强现有的小部件,或者可以从头开始创建自定义小部件。

刻录小部件

这是我们从头开始创建的小部件的示例。 可以在各种媒体刻录应用(例如 K3B)中找到此小部件。

custom.rb

  1. #!/usr/bin/ruby
  2. '''
  3. ZetCode Ruby GTK tutorial
  4. This example creates a custom widget.
  5. Author: Jan Bodnar
  6. Website: www.zetcode.com
  7. Last modified: May 2014
  8. '''
  9. require 'gtk3'
  10. class Burning < Gtk::DrawingArea
  11. def initialize parent
  12. @parent = parent
  13. super()
  14. @num = [ "75", "150", "225", "300",
  15. "375", "450", "525", "600", "675" ]
  16. set_size_request 1, 30
  17. signal_connect "draw" do
  18. on_draw
  19. end
  20. end
  21. def on_draw
  22. cr = window.create_cairo_context
  23. draw_widget cr
  24. end
  25. def draw_widget cr
  26. cr.set_line_width 0.8
  27. cr.select_font_face "Courier",
  28. Cairo::FONT_SLANT_NORMAL, Cairo::FONT_WEIGHT_NORMAL
  29. cr.set_font_size 11
  30. width = allocation.width
  31. @cur_width = @parent.get_cur_value
  32. step = (width / 10.0).round
  33. till = (width / 750.0) * @cur_width
  34. full = (width / 750.0) * 700
  35. if @cur_width >= 700
  36. cr.set_source_rgb 1.0, 1.0, 0.72
  37. cr.rectangle 0, 0, full, 30
  38. cr.clip
  39. cr.paint
  40. cr.reset_clip
  41. cr.set_source_rgb 1.0, 0.68, 0.68
  42. cr.rectangle full, 0, till-full, 30
  43. cr.clip
  44. cr.paint
  45. cr.reset_clip
  46. else
  47. cr.set_source_rgb 1.0, 1.0, 0.72
  48. cr.rectangle 0, 0, till, 30
  49. cr.clip
  50. cr.paint
  51. cr.reset_clip
  52. end
  53. cr.set_source_rgb(0.35, 0.31, 0.24)
  54. for i in 1..@num.length
  55. cr.move_to i*step, 0
  56. cr.line_to i*step, 5
  57. cr.stroke
  58. te = cr.text_extents @num[i-1]
  59. cr.move_to i*step-te.width/2, 15
  60. cr.text_path @num[i-1]
  61. cr.stroke
  62. end
  63. end
  64. end
  65. class RubyApp < Gtk::Window
  66. def initialize
  67. super
  68. set_title "Burning"
  69. signal_connect "destroy" do
  70. Gtk.main_quit
  71. end
  72. set_size_request 350, 200
  73. set_window_position :center
  74. @cur_value = 0
  75. vbox = Gtk::Box.new :vertical, 2
  76. scale = Gtk::Scale.new :horizontal
  77. scale.set_range 0, 750
  78. scale.set_digits 0
  79. scale.set_size_request 160, 35
  80. scale.set_value @cur_value
  81. scale.signal_connect "value-changed" do |w|
  82. on_changed w
  83. end
  84. fix = Gtk::Fixed.new
  85. fix.put scale, 50, 50
  86. vbox.pack_start fix
  87. @burning = Burning.new self
  88. vbox.pack_start @burning, :expand => false,
  89. :fill => false, :padding => 0
  90. add vbox
  91. show_all
  92. end
  93. def on_changed widget
  94. @cur_value = widget.value
  95. @burning.queue_draw
  96. end
  97. def get_cur_value
  98. return @cur_value
  99. end
  100. end
  101. Gtk.init
  102. window = RubyApp.new
  103. Gtk.main

我们在窗口底部放置一个Gtk::DrawingArea并手动绘制整个窗口小部件。 所有重要的代码都驻留在draw_widget中,这是从 Burning 类的on_draw方法调用的。 此小部件以图形方式显示介质的总容量和可用空间。 该小部件由比例小部件控制。 自定义窗口小部件的最小值为 0,最大值为 750。如果值达到 700,则开始绘制红色。 这通常表示过度燃烧。

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

这些数字显示在刻录小部件上。 它们显示了介质的容量。

  1. @cur_width = @parent.get_cur_value

从父小部件中,我们获得了比例小部件的当前值。

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

我们使用width变量在小数位的值和自定义小部件的度量之间进行转换。 请注意,我们使用浮点值-在绘图中获得更高的精度。 till参数确定要绘制的总大小。 该值来自滑块小部件。 它占整个面积的一部分。 full参数确定我们开始绘制红色的点。

  1. cr.set_source_rgb 1.0, 1.0, 0.72
  2. cr.rectangle 0, 0, till, 30
  3. cr.clip
  4. cr.paint
  5. cr.reset_clip

我们绘制一个黄色矩形,直到介质充满的地方。

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

这里的代码在刻录小部件上绘制数字。 我们计算文本范围以正确定位文本。

  1. def on_changed widget
  2. @cur_value = widget.value
  3. @burning.queue_draw
  4. end

我们从小部件中获取值,并将其存储在@cur_value变量中以备后用。 我们重新绘制刻录的小部件。

Ruby GTK 中的自定义小部件 - 图1

图:刻录小部件

在本章中,我们使用 GTK 和 Ruby 编程语言创建了一个自定义小部件。