HowTo : BoxSizer - mcorino/wxRuby3 GitHub Wiki

In this tutorial we will discuss the wxRuby BoxSizer Layout Sizer.
The BoxSizer is one of the sizers in wxRuby designed to help with the layout management of widgets in the window. The BoxSizer is the most basic and commonly used Sizer in wxRuby. Every GUI library has a Layout manager like the BoxSizer.
It’s a fairly simple Sizer that simply stacks widgets vertically or horizontally depending on the orientation setting specified at creation. It doesn’t have a lot of utility alone, but when using several BoxSizers nested within each other, complex GUI layouts can be created easily.
In this example we will create a simple BoxSizer with two widgets placed inside it.
First we create the BoxSizer, passing in either Wx::VERTICAL or Wx::HORIZONTAL to set the orientation of how widgets will be placed.
sizer = Wx::BoxSizer.new(wx.VERTICAL)
Note: wxRuby provides two simple but useful shortcut derivatives that will make code easier to write and read: Wx::HBoxSizer and Wx::VBoxSizer
Next we add individual widgets in this manner.
button1 = Wx::Button.new(@panel, label: 'Button 1')
sizer.add(button1)
Alternatively, we could add them directly like this.
sizer.add(Wx::Button.new(@panel, label: 'Button 1'))
After adding all the widgets we want to, we simply call the #set_sizer method on the panel in which we are creating all these widgets.
@panel.set_sizer(sizer)
The complete code and output is as follows.
require 'wx'
class MyWindow < Wx::Frame
def initialize(title)
super(nil, title: title)
@panel = Wx::Panel.new(self)
sizer = Wx::BoxSizer.new(Wx::VERTICAL) # or Wx::VBoxSizer.new
button1 = Wx::Button.new(@panel, label: 'Button 1')
sizer.add(button1)
button2 = Wx::Button.new(@panel, label: 'Button 2')
sizer.add(button2)
@panel.sizer = sizer
centre
end
end
Wx::App.run do
window = MyWindow.new("wxRuby BoxSizer Guide")
window.show
end
The output:
In this example we’ll begin using some of the additional options and parameters to add more functionality to our widgets in the BoxSizer.
The #add method has three additional, optional arguments.
proportion : This argument is 0 by default which means that the size of the widget is unchangeable. Any value above 0 will change the size of the widgets relative to value in the other widgets (for example a widget with proportion 2 will grow twice as much as a widget with proportion 1) as the sizer changes size.
flag : A combination of flags which are used to change certain things about the sizer (no flags are set by default).
border
: The amount of padding to be used between widgets (0 by default). Needs to be used together with the appropriate flag (for example,
using Wx::ALL
will apply padding on all sides).
Below is a simple example using the BoxSizer with a bunch of additional arguments and options enabled.
require 'wx'
class MyWindow < Wx::Frame
def initialize(title)
super(nil, title: title)
@panel = Wx::Panel.new(self)
sizer = Wx::BoxSizer.new(Wx::VERTICAL) # or Wx::VBoxSizer.new
button1 = Wx::Button.new(@panel, label: 'Button 1')
sizer.add(button1, 1, Wx::ALL | Wx::EXPAND, 5)
button2 = Wx::Button.new(@panel, label: 'Button 2')
sizer.add(button2, flag: Wx::ALL, border: 5)
@panel.sizer = sizer
centre
end
end
Wx::App.run do
window = MyWindow.new("wxRuby BoxSizer Guide")
window.show
end
The first button has the proportion set to 1, so it expands unlike button 2. There is also some extra padding between the two buttons. The output:
Note: As can be seen in the example wxRuby supports either passing the (full set of) optional arguments in positional order or passing them as keyword arguments (all or some, in any order ).
Now let’s try to make something more practical. For this, we’ll use the rather interesting concept of nested sizers. You can add a Sizer into another Sizer the same way you add widgets, using the #add method.
require 'wx'
class MyWindow < Wx::Frame
def initialize(title)
super(nil, title: title)
@panel = Wx::Panel.new(self)
sizer = Wx::BoxSizer.new(Wx::VERTICAL) # or Wx::VBoxSizer.new
#-----------------------
sub_sizer1 = Wx::BoxSizer.new(Wx::HORIZONTAL) # or Wx::HBoxSizer.new
text1 = Wx::StaticText.new(@panel, label: 'Username: ')
sub_sizer1.add(text1, Wx::SizerFlags.new.border(Wx::ALL, 5))
text2 = Wx::TextCtrl.new(@panel)
sub_sizer1.add(text2, Wx::SizerFlags.new(1).border(Wx::ALL, 5))
#-----------------------
#-----------------------
sub_sizer2 = Wx::HBoxSizer.new
text3 = Wx::StaticText.new(@panel, label: 'Password: ')
sub_sizer2.add(text3, Wx::SizerFlags.new.border(Wx::ALL, 5))
text4 = Wx::TextCtrl.new(@panel)
sub_sizer2.add(text4, Wx::SizerFlags.new(1).border(Wx::ALL, 5))
#-----------------------
sizer.add(sub_sizer1, Wx::SizerFlags.new.expand.border(Wx::TOP|Wx::LEFT, 10))
sizer.add(sub_sizer2, Wx::SizerFlags.new.expand.border(Wx::TOP|Wx::LEFT, 10))
@panel.sizer = sizer
centre
end
end
Wx::App.run do
window = MyWindow.new("wxRuby Sizer Guide")
window.show
end
The layout below, despite being fairly simple, would not be possible with just a single Sizer. For such things, we require multiple sizers. Output of the above code:
There are many other Sizers in wxRuby that you can use instead of BoxSizer. In fact, the best layouts are often the result of combining several different types of Sizers. This can be done by simply nesting them into each other. There is no limitation to this ability.
- StaticBoxSizer (a variant of BoxSizer)
- WrapSizer (another variant of BoxSizer)
- GridSizer
- FlexGridSizer (a variant of GridSizer)
- GridBagSizer (a variant of FlexGridSizer)
You can learn more about these sizers by reading the guide on layout managers in wxRuby.