Using the RubyGnome2 library for the basic method of Ruby GUI programming under GTK,
Preface
As the RubyGnome2 library becomes more and more perfect and ruby1.9 performance is improved, writing GUI programs in Ruby has gradually changed from my hobbies to an important part of my work.
Writing a program in Ruby is really fun. It allows you to quickly implement your ideas in an elegant way. The gem introduced in this article is an example. It uses very little code to implement interesting functions, making it easy and pleasant to compile Ruby GUI programs.
RubyGnome2 Introduction
Although I have introduced RubyGnome2 many times before, I still want to recommend RubyGnome2 again, which is the first choice for compiling GUI programs using Ruby.
RubyGnome2 is a ruby extension of the GTK + Library. It carefully encapsulates the GTK + Object Model in Ruby mode and retains the GTK + API naming method and meaning, therefore, the GTK + documentation is also applicable to RubyGnome2-although I think the document of RubyGnome2 has done a very good job, there are not many places to learn from the GTK documentation.
Although GTK is compiled by C itself, it has a complete set of well-designed object systems, allowing its GUI components to be flexibly and freely combined to achieve complex, powerful interfaces.
Since GTK attaches great importance to the flexibility of its object system, it is not easy to start using GTK programming. Most of the time, on the surface, it looks very simple. In GTK, it takes several turns to achieve this. For example, to set a label font, you must use Pango. Pango takes over all the font rendering transactions of GTK .... this kind of "more turns around a few turns" makes it really less straightforward to write GTK programs. But in exchange, the entire GTK system becomes very flexible and provides powerful functions at a low cost. It has a good performance in cross-platform, skin-changing, and internationalization.
RubyGnome2 inherits all the features of GTK, including its advantages and disadvantages.
GUI Layout
The layout of the GTK program is flexible and there are many containers to choose from. In the layout, most of them are recommended relative positions rather than absolute positions, so that GUI programs can better adapt to screens with different resolutions, and also facilitate the fine tune of the UI in specific styles.
The most common containers are "Boxes", including "Horizontal boxes" and "vertical boxes ". Put visual UI elements into a "box", and different "Boxes" are combined and stacked to build a target layout.
Theoretically, a box can be used to build any relative layout, but GTK also provides a more advanced container like table.
The box model is difficult for many people who have just begun GTK programming, that is, they use visual layout tools such as Glade, and beginners are often troubled by the box model. The visual la er is best at fixed-position la S. For relative location layout, it is more convenient to use code to build the interface than to use Glade.
However, building interfaces with code has a notable drawback, that is, "not intuitive", that is, it is difficult to see the UI layout from the code, which will cause trouble for later maintenance and changes.
Some GUI Libraries such as Shose use builder-style code to describe the UI, so that the UI layout can be reflected in the Code image. The following example is from shooose.net:
Shoes.app {
stack(:margin => 4) {
button "Mice"
button "Eagles"
button "Quail"
}
}
In this way, we can see the UI layout from the code.
Builder-style code is similar to HTML. For web interface designers familiar with HTML, visual editor is not necessary.
RubyGnome2 does not provide us with a builder layout, so the UI code is written like:
Shoes.app {
stack(:margin => 4) {
button "Mice"
button "Eagles"
button "Quail"
}
}
From the code above, it is difficult to see the UI layout at once.
If you also build a builder-style layout for RubyGnome2, the code will become:
class MyWin < Gtk::Window
def initialize
super
add my_layout
end
def my_layout
vbox do
button 'Mice'
button 'Eagles'
button 'Quail'
end
end
end
Well, this code is similar to Shose. You can see the UI layout from the code.
One of the functions of GtkSimpleLayout described in this article is to provide a builder layout for RubyGnome2.
GtkSimpleLayout
This simple la er originally had less than 200 lines of code, which I often directly copied to the project for use. Later, I gradually added some features and thought they became more useful. So I released them to github to generate a gem for users who are interested in it.
Source: git: // github.com/rickyzheng/GtkSimpleLayout.git
Or:
Gem source-a http://gems.github.com & gem install rickyzheng-GtkSimpleLayout
The following describes the main functions and simple examples.
Provides Builder Layout
As described in the above example, GtkSimpleLayout provides the builder layout function for RubyGnome2. You only need to extend GtkSimpleLayout: Base for the layout class. A complete example:
require 'gtk2'
require 'simple_layout'
class MyWin < Gtk::Window
include SimpleLayout::Base
def initialize
super
add my_layout
signal_connect('destroy') do
Gtk.main_quit
end
end
def my_layout
hbox do
label 'Hello, '
button 'World !'
end
end
end
MyWin. new. show_all
Gtk. main
As shown in the preceding example, GtkSimpleLayout does not change the main framework of the RubyGnome2 program. It is just an extension.
Attribute settings
When placing the UI component, you often need to set the initial attribute or specify the layout parameters. GtkSimpleLayout uses Hash to pass these attributes and parameters, for example:
vbox do
button 'sensitive = false',: sensitive => false # Initially disabled
button 'expand space',: layout => [true, true] # specify that this button fills the remaining space
end
In the preceding example, the initial status of the first button is disable. ": Sensitive => false" is converted to the Property setting: Gtk: Button # sensitive = false. For Gtk: Button, you can set the attributes, see the RubyGnome2 API document or GTK document. GtkSimpleLayout is just a simple parameter conversion here.
The ": layout => [true, true]" of the second button is special. ": Layout" is the reserved parameter of GtkSimpleLayout, which is converted to the parameter when the UI is put into the container. In this example, the container is vbox (Gtk: VBox), and the default addition method is Gtk: VBox # pack_start. In this example, [true, true] will be passed to pack_start. Therefore, when this button is added to vbox, the call method and parameter are: "Gtk: VBox # pack_start (button, true, true) ".
Therefore, to use GtkSimpleLayout, you must first familiarize yourself with the components of RubyGnome2, container usage, and parameters. When you are familiar with RubyGnome2, using GtkSimpleLayout will be very simple.
Batch attribute settings
During UI layout, you often encounter the situation where you need to set the same attributes for a group of UI elements, such:
hbox do
button 'C', :layout => [false, false, 5]
button 'D', :layout => [false, false, 5]
button 'E', :layout => [false, false, 5]
end
In this case, you can use "with_attr" to simplify the process:
hbox do
with_attr :layout => [false, false, 5] do
button 'C'
button 'D'
button 'E'
end
end
Special container
Some containers have special requirements for sub-components, such as Gtk: HPaned. The left-side sub-window must be added with Gtk: HPaned # add1 (), and the right side should be added with Gtk :: HPaned # add2 (). For such containers, GtkSimpleLayout should be specially treated. Take hpaned as an example:
hpaned do
area_first do
frame 'first area'
end
area_second do
frame 'second area'
end
end
Containers that require special treatment include:
Hpaned/vpaned: Use area_first and area_second to add subwindows.
Table: Use a grid to fill the grid.
Nodebook: Use page to add subpages.
Identify the UI component
Use ": id => ?? "This parameter is identified by the UI component, for example:
hbox do
button 'first', :id => :btn_first
button 'second', :id => :btn_second
end
You can use the component () function to obtain the UI component:
my_first_button = component(:btn_first)
my_second_button = component(:btn_second)
...
my_first_button.signal_connect('clicked') do
puts "first button clicked"
end
my_second_button.signal_connect('clicked') do
puts "second button clicked"
end
If it is too troublesome, GtkSimpleLayout also provides expose_components () to automatically add all identified elements as the instance read attribute (getter ):
Expose_components () # The two read attributes (getter) btn_first and btn_second will be automatically added ).
...
btn_first.signal_connect('clicked') do
puts "first button clicked"
end
btn_second.signal_connect('clicked') do
puts "second button clicked"
end
Automatic Event Response ing
If you explicitly call signal_connect to register events, GtkSimpleLayout provides you with the automatic Event Response ing function:
require 'gtk2'
require 'simple_layout'
class MyWin <Gtk :: Window
include SimpleLayout :: Base
def initialize
super
add my_layout
register_auto_events () # Register automatic event response mapping
end
def my_layout
hbox do
button "First ',: btn_first
button "Second",: btn_second
end
end
# Event response function
def btn_first_on_clicked (* _)
puts "First button clicked"
end
# Event response function
def btn_second_on_clicked (* _)
puts "Second button clicked"
end
# Exit event response function
def self_on_destroy (* _)
Gtk.main_quit
end
end
The last 'self 'refers to the host container.
UI group
Sometimes you want to group the UI components so that you can control the UI components in the same group, such as enabling or disabling the entire group. GtkSimpleLayout allows you to specify the UI group during layout.
The UI grouping rules of GtkSimpleLayout are as follows:
By default, the named container (that is, the input: id parameter) automatically creates a group for its child components. The group name is the container name.
If the container is passed in: gid => ?? Parameter.
Multiple containers are allowed with the same gid name. In this case, the sub-components are grouped into the same group.
You can use "group" to explicitly group the UI. A group can be considered as a virtual container.
Use component_children (group_name) to obtain the UI group.
The examples of UI grouping are not listed here for a long time. For details, refer to the examples/group. rb file in the source code.
Separation of UI and logic code
GtkSimpleLayout potentially forces the user to separate the interface code from the logic processing (or Event Response) Code, making the hierarchy of the entire program clearer. For programs with many interface elements, layout can be easily partitioned. Because the result of layout is still a container, this container can be combined into other containers to form a more complex interface.
Because GtkSimpleLayout does not change the program structure of RubyGnome2, you can choose to use GtkSimpleLayout in part or all of your programs. Although the examples provided in this article are static la s, because GtkSimpleLayout is used to store code to build the UI, You can input variables during layout for Dynamic Layout and UI generation, the UI code is still visualized ".
If you are interested, you can look at the Code implemented by GtkSimpleLayout, but there are only 300 lines. This is Ruby's charm.
Finally, you can see the UI layout from the code by pasting the code example of a calculator interface?
require 'gtk2'
require 'simple_layout'
class MyWin < Gtk::Window
include SimpleLayout::Base
def initialize
super
add my_layout
signal_connect('destroy') do
Gtk.main_quit
end
end
def my_layout
vbox do
with_attr :border_width => 3 do
hbox do
entry :id => :ent_input, :layout => [true, true, 5]
end
hbox do
frame do
label 'M', :set_size_request => [20, 20]
end
hbutton_box do
button 'Backspace'
button 'CE'
button 'C'
end
end
hbox do
vbutton_box do
button 'MC'
button 'MR'
button 'MS'
button 'M+'
end
with_attr :layout => [true, true] do
number_and_operators_layout
end
end
end
end
end
def number_and_operators_layout
vbox do
[ ['7', '8', '9', '/', 'sqt'],
['4', '5', '6', '*', '%'],
['1', '2', '3', '-', '1/x'],
['0', '+/=', '.', '+', '=']].each do |cols|
hbox :layout => [true, true] do
cols.each do |txt|
button txt, :set_size_request => [20, 20], :layout => [true, true]
end
end
end
end
end
end
MyWin. new. show_all
Gtk. main
Enjoy it :-)