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

在本章中,我们将展示如何在窗口或对话框上布置窗口小部件。

在设计应用的 GUI 时,我们决定使用哪些小部件以及如何在应用中组织这些小部件。 为了组织窗口小部件,我们使用称为布局容器的专用非可见窗口小部件。 在本章中,我们提到Gtk::AlignmentGtk::FixedGtk::VBoxGtk::Grid

Gtk::Fixed

Gtk::Fixed容器将子窗口小部件放置在固定位置并具有固定大小。 此容器不执行自动布局管理。 在大多数应用中,我们不使用此容器。 我们在某些特定领域使用它,例如游戏,使用图表的应用,可以移动的可调整大小的组件(例如电子表格应用中的图表),小型教育示例。

  1. #!/usr/bin/ruby
  2. '''
  3. ZetCode Ruby GTK tutorial
  4. In this program, we lay out widgets
  5. using absolute positioning.
  6. Author: Jan Bodnar
  7. Website: www.zetcode.com
  8. Last modified: May 2014
  9. '''
  10. require 'gtk3'
  11. class RubyApp < Gtk::Window
  12. def initialize
  13. super
  14. init_ui
  15. end
  16. def init_ui
  17. override_background_color :normal, Gdk::RGBA::new(0.2, 0.2, 0.2, 1)
  18. begin
  19. bardejov = Gdk::Pixbuf.new :file => "bardejov.jpg"
  20. rotunda = Gdk::Pixbuf.new :file => "rotunda.jpg"
  21. mincol = Gdk::Pixbuf.new :file => "mincol.jpg"
  22. rescue IOError => e
  23. puts e
  24. puts "cannot load images"
  25. exit
  26. end
  27. image1 = Gtk::Image.new :pixbuf => bardejov
  28. image2 = Gtk::Image.new :pixbuf => rotunda
  29. image3 = Gtk::Image.new :pixbuf => mincol
  30. fixed = Gtk::Fixed.new
  31. fixed.put image1, 20, 20
  32. fixed.put image2, 40, 160
  33. fixed.put image3, 170, 50
  34. add fixed
  35. set_title "Fixed"
  36. signal_connect "destroy" do
  37. Gtk.main_quit
  38. end
  39. set_default_size 300, 280
  40. window_position = :center
  41. show_all
  42. end
  43. end
  44. Gtk.init
  45. window = RubyApp.new
  46. Gtk.main

在我们的示例中,我们在窗口上显示了三个小图像。 我们明确指定放置这些图像的 x,y 坐标。

  1. override_background_color :normal, Gdk::RGBA::new(0.2, 0.2, 0.2, 1)

为了获得更好的视觉体验,我们将背景色更改为深灰色。

  1. bardejov = Gdk::Pixbuf.new :file => "bardejov.jpg"

我们将图像从磁盘加载到Gtk::Pixbuf对象。

  1. image1 = Gtk::Image.new :pixbuf => bardejov
  2. image2 = Gtk::Image.new :pixbuf => rotunda
  3. image3 = Gtk::Image.new :pixbuf => mincol

Gtk::Image是用于显示图像的小部件。 它在构造器中使用一个Gdk::Pixbuf对象。

  1. fixed = Gtk::Fixed.new

我们创建Gtk::Fixed容器。

  1. fixed.put image1, 20, 20

我们将第一个图像放置在 x = 20,y = 20 坐标处。

  1. add fixed

最后,我们将Gtk::Fixed容器添加到窗口中。

Ruby GTK 中的布局管理 - 图1

图:Gtk::Fixed

按钮

Gtk::Alignment容器控制其子窗口小部件的对齐方式和大小。

  1. #!/usr/bin/ruby
  2. '''
  3. ZetCode Ruby GTK tutorial
  4. In this program, we position two buttons
  5. in the bottom right corner of the window.
  6. We use horizontal and vertical boxes.
  7. Author: Jan Bodnar
  8. Website: www.zetcode.com
  9. Last modified: May 2014
  10. '''
  11. require 'gtk3'
  12. class RubyApp < Gtk::Window
  13. def initialize
  14. super
  15. init_ui
  16. end
  17. def init_ui
  18. set_border_width 10
  19. vbox = Gtk::Box.new :vertical, 0
  20. hbox = Gtk::Box.new :horizontal, 5
  21. e_space = Gtk::Alignment.new 0, 0, 0, 0
  22. vbox.pack_start e_space, :expand => true
  23. ok_btn = Gtk::Button.new :label => "OK"
  24. ok_btn.set_size_request 70, 30
  25. close_btn = Gtk::Button.new :label => "Close"
  26. close_btn.set_size_request 70, 30
  27. hbox.add ok_btn
  28. hbox.add close_btn
  29. halign = Gtk::Alignment.new 1, 0, 0, 0
  30. halign.add hbox
  31. vbox.pack_start halign, :expand => false,
  32. :fill => false, :padding => 5
  33. add vbox
  34. set_title "Buttons"
  35. signal_connect "destroy" do
  36. Gtk.main_quit
  37. end
  38. set_default_size 260, 150
  39. set_window_position :center
  40. show_all
  41. end
  42. end
  43. Gtk.init
  44. window = RubyApp.new
  45. Gtk.main

在代码示例中,我们在窗口的右下角放置了两个按钮。 为此,我们使用一个水平框,一个垂直框和两个对齐容器。

  1. set_border_width 10

set_border_widthGtk::Window容器窗口小部件的边框周围设置了一些空白。 对于我们的示例来说很重要,因为关闭按钮不会太靠近窗口的右边缘。

  1. vbox = Gtk::Box.new :vertical, 0
  2. hbox = Gtk::Box.new :horizontal, 5

将创建一个垂直和水平框。 垂直框用作我们窗口的基础容器。 垂直框中放置有空白空间和包含两个按钮小部件的水平框。

  1. e_space = Gtk::Alignment.new 0, 0, 0, 0
  2. vbox.pack_start e_space, :expand => true

Gtk::Alignment小部件用作空白填充符。 它将按钮推到窗口底部。 :expand参数将导致Gtk::Alignment小部件消耗分配给垂直框的所有额外空间。

  1. hbox = Gtk::Box.new :horizontal, 5
  2. ...
  3. ok_btn = Gtk::Button.new :label => "OK"
  4. ok_btn.set_size_request 70, 30
  5. close_btn = Gtk::Button.new :label => "Close"
  6. close_btn.set_size_request 70, 30
  7. hbox.add ok_btn
  8. hbox.add close_btn

我们创建一个水平框,并在其中放置两个按钮。 Gtk::Box的第二个参数是子级之间的间距量。

  1. halign = Gtk::Alignment.new 1, 0, 0, 0
  2. halign.add hbox
  3. vbox.pack_start halign, :expand => false,
  4. :fill => false, :padding => 5

这将创建一个对齐容器,它将其子窗口小部件放在右侧。 Gtk::Alignment容器的第一个参数是水平对齐方式。 值为 1 会将其子项(包含两个按钮的水平框)向右推。 对齐容器仅需要一个子窗口小部件-我们必须使用水平框。

Ruby GTK 中的布局管理 - 图2

图:按钮

计算器骨架

本示例借助Gtk::BoxGtk::Grid小部件创建计算器的骨架。

  1. #!/usr/bin/ruby
  2. '''
  3. ZetCode Ruby GTK tutorial
  4. In this program we create a skeleton of
  5. a calculator. We use a Gtk::Grid widget
  6. and a vertical Gtk::Box.
  7. Author: Jan Bodnar
  8. Website: www.zetcode.com
  9. Last modified: May 2014
  10. '''
  11. require 'gtk3'
  12. class RubyApp < Gtk::Window
  13. def initialize
  14. super
  15. init_ui
  16. end
  17. def init_ui
  18. vbox = Gtk::Box.new :vertical, 2
  19. mb = Gtk::MenuBar.new
  20. filemenu = Gtk::Menu.new
  21. file = Gtk::MenuItem.new "File"
  22. file.set_submenu filemenu
  23. mb.append file
  24. vbox.pack_start mb, :expand => false, :fill => false,
  25. :padding => 0
  26. vbox.pack_start Gtk::Entry.new, :expand => false,
  27. :fill => false, :padding => 0
  28. grid = Gtk::Grid.new
  29. grid.set_property "row-homogeneous", true
  30. grid.set_property "column-homogeneous", true
  31. grid.attach Gtk::Button.new(:label => "Cls"), 0, 0, 1, 1
  32. grid.attach Gtk::Button.new(:label => "Bck"), 1, 0, 1, 1
  33. grid.attach Gtk::Label.new, 2, 0, 1, 1
  34. grid.attach Gtk::Button.new(:label => "Close"), 3, 0, 1, 1
  35. grid.attach Gtk::Button.new(:label => "7"), 0, 1, 1, 1
  36. grid.attach Gtk::Button.new(:label => "8"), 1, 1, 1, 1
  37. grid.attach Gtk::Button.new(:label => "9"), 2, 1, 1, 1
  38. grid.attach Gtk::Button.new(:label => "/"), 3, 1, 1, 1
  39. grid.attach Gtk::Button.new(:label => "4"), 0, 2, 1, 1
  40. grid.attach Gtk::Button.new(:label => "5"), 1, 2, 1, 1
  41. grid.attach Gtk::Button.new(:label => "6"), 2, 2, 1, 1
  42. grid.attach Gtk::Button.new(:label => "*"), 3, 2, 1, 1
  43. grid.attach Gtk::Button.new(:label => "1"), 0, 3, 1, 1
  44. grid.attach Gtk::Button.new(:label => "2"), 1, 3, 1, 1
  45. grid.attach Gtk::Button.new(:label => "3"), 2, 3, 1, 1
  46. grid.attach Gtk::Button.new(:label => "-"), 3, 3, 1, 1
  47. grid.attach Gtk::Button.new(:label => "0"), 0, 4, 1, 1
  48. grid.attach Gtk::Button.new(:label => "."), 1, 4, 1, 1
  49. grid.attach Gtk::Button.new(:label => "="), 2, 4, 1, 1
  50. grid.attach Gtk::Button.new(:label => "+"), 3, 4, 1, 1
  51. vbox.pack_start grid, :expand => true, :fill => true,
  52. :padding => 0
  53. add vbox
  54. set_title "Calculator"
  55. signal_connect "destroy" do
  56. Gtk.main_quit
  57. end
  58. set_default_size 300, 250
  59. set_window_position :center
  60. show_all
  61. end
  62. end
  63. Gtk.init
  64. window = RubyApp.new
  65. Gtk.main

Gtk::Grid小部件按行和列排列小部件。

  1. vbox = Gtk::Box.new :vertical, 2

Gtk::Box用作我们应用的基础容器。 框的方向是垂直的,其子框(菜单栏,条目和网格小部件)之间有 2px 的间距。 由于它是一个垂直框,因此该空间垂直放置在小部件之间。

  1. mb = Gtk::MenuBar.new
  2. filemenu = Gtk::Menu.new
  3. file = Gtk::MenuItem.new "File"
  4. file.set_submenu filemenu
  5. mb.append file
  6. vbox.pack_start mb, :expand => false, :fill => false,
  7. :padding => 0

创建带有一个菜单的Gtk::MenuBar。 它放置在垂直框内。

  1. vbox.pack_start Gtk::Entry.new, :expand => false,
  2. :fill => false, :padding => 0

Gtk::Entry放置在菜单栏下方。 我们将:expand参数设置为false,因为我们不想垂直扩展条目窗口小部件。 放在垂直框中的小部件从左向右拉伸。 如果要更改此设置,则需要一个附加的水平框。

  1. grid = Gtk::Grid.new

Gtk::Grid容器已创建。

  1. grid.set_property "row-homogeneous", true
  2. grid.set_property "column-homogeneous", true

我们将行和列的均质属性设置为true。 这将导致所有子项具有相同的大小。

  1. grid.attach Gtk::Button.new(:label => "Cls"), 0, 0, 1, 1

我们在网格容器的左上角单元格上附加一个按钮。 前两个参数是列索引和行索引。 最后两个参数是列跨度和行跨度。 网格内的所有小部件都占用一个单元格。

  1. vbox.pack_start grid, :expand => true, :fill => true,
  2. :padding => 0

我们将网格小部件打包到垂直框中。 :expand:fill选项的组合将使网格小部件及其子级占据窗口区域的大部分。

  1. add vbox

垂直框放置在Gtk::Window容器内。

Ruby GTK 中的布局管理 - 图3

图:计算机骨架

窗口

在最后一个示例中,我们将使用Gtk::Grid容器。 此容器将其子级放置到单元格中,这些单元格由行和列的交点界定。 网格容器的attach方法采用五个参数。 第一个参数是附加的子窗口小部件。 接下来的两个参数是放置子项的行和列索引。 最后两个参数是行跨度和列跨度。

  1. #!/usr/bin/ruby
  2. '''
  3. ZetCode Ruby GTK tutorial
  4. This is a more complicated layout example.
  5. We use Gtk::Alignment, Gtk::Box, and Gtk::Grid widgets.
  6. Author: Jan Bodnar
  7. Website: www.zetcode.com
  8. Last modified: May 2014
  9. '''
  10. require 'gtk3'
  11. class RubyApp < Gtk::Window
  12. def initialize
  13. super
  14. init_ui
  15. end
  16. def init_ui
  17. set_border_width 15
  18. grid = Gtk::Grid.new
  19. grid.set_column_spacing 5
  20. grid.set_row_spacing 5
  21. title = Gtk::Label.new "Windows"
  22. align1 = Gtk::Alignment.new 0, 0, 0, 0
  23. align1.add title
  24. grid.attach align1, 0, 0, 1, 1
  25. frame = Gtk::Frame.new
  26. frame.set_hexpand true
  27. frame.set_vexpand true
  28. grid.attach frame, 0, 1, 3, 3
  29. vbox = Gtk::Box.new :vertical, 4
  30. act_btn = Gtk::Button.new :label => "Activate"
  31. act_btn.set_size_request 70, 30
  32. close_btn = Gtk::Button.new :label => "Close"
  33. close_btn.set_size_request 70, 30
  34. vbox.add act_btn
  35. vbox.add close_btn
  36. grid.attach vbox, 3, 1, 1, 1
  37. help_btn = Gtk::Button.new :label => "Help"
  38. help_btn.set_size_request 70, 30
  39. align2 = Gtk::Alignment.new 0, 0, 0, 0
  40. align2.add help_btn
  41. grid.attach align2, 0, 4, 1, 1
  42. ok_btn = Gtk::Button.new :label => "OK"
  43. ok_btn.set_size_request 70, 30
  44. grid.attach ok_btn, 3, 4, 1, 1
  45. add grid
  46. set_title "Windows"
  47. signal_connect "destroy" do
  48. Gtk.main_quit
  49. end
  50. set_default_size 350, 300
  51. set_window_position :center
  52. show_all
  53. end
  54. end
  55. Gtk.init
  56. window = RubyApp.new
  57. Gtk.main

该代码在 Ruby GTK 中创建了一个真实世界的窗口。

  1. grid = Gtk::Grid.new
  2. grid.set_column_spacing 5
  3. grid.set_row_spacing 5

创建Gtk::Grid容器的实例。 该容器将小部件打包为行和列。 我们在行和列之间设置一些空间。

  1. title = Gtk::Label.new "Windows"
  2. align1 = Gtk::Alignment.new 0, 0, 0, 0
  3. align1.add title
  4. grid.attach align1, 0, 0, 1, 1

我们创建一个标签小部件。 将此小部件放置在Gtk::Alignment小部件中,以便使其与标签上的空格左侧对齐。 网格容器的attach方法将标签放入其左上角的单元格中。 标签将占据一个单元格。

  1. frame = Gtk::Frame.new
  2. frame.set_hexpand true
  3. frame.set_vexpand true
  4. grid.attach frame, 0, 1, 3, 3

框架小部件位于column = 0row = 1处。 它跨越三行和树列。 set_hexpandset_vexpand方法将窗口小部件设置为占用任何可用的额外水平和垂直空间。 当窗口增长时,框架小部件也增长; 其他小部件保留其大小。

  1. vbox = Gtk::Box.new :vertical, 4
  2. act_btn = Gtk::Button.new :label => "Activate"
  3. act_btn.set_size_request 70, 30
  4. close_btn = Gtk::Button.new :label => "Close"
  5. close_btn.set_size_request 70, 30
  6. vbox.add act_btn
  7. vbox.add close_btn
  8. grid.attach vbox, 3, 1, 1, 1

创建两个按钮并将其放置在垂直框中。 “到”框位于框架小部件旁边。

  1. help_btn = Gtk::Button.new :label => "Help"
  2. help_btn.set_size_request 70, 30
  3. align2 = Gtk::Alignment.new 0, 0, 0, 0
  4. align2.add help_btn
  5. grid.attach align2, 0, 4, 1, 1

帮助按钮位于对齐容器内部,该对齐按钮将其对齐到网格容器旁边放置的单元格的左侧。 较早的set_hexpand方法调用使框架窗口小部件可扩展; 它还会影响框架窗口小部件占用的列中的窗口小部件。 因此,我们需要使用Gtk::Alignment小部件来保持按钮的大小不变,并将其向左对齐。

Ruby GTK 中的布局管理 - 图4

图:窗口

在 Ruby GTK 教程的这一部分中,我们提到了小部件的布局管理。