Multiple forms or panels


#1

How do I organize widgets in a form when I need them placed in more than
a single column or row? I leaned how to use BoxSizer and successfully
displayed my widgets in a single column but can’t get the next column.

Here is my code, which puts a text, radio, button all in one column, but
what if I wanted my radios over to the right?:

require “rubygems”
require “wx”
include Wx

class MyFrame < Frame
def initialize
super(nil, :title => “My Test Frame”)

@panel = Panel.new(self)
@result = StaticText.new(@panel, :label=>'Result')
@y = TextCtrl.new(@panel, -1, '10')
shape_choice = %w(Circular Rectangular Trapezoidal )

submit_button = Button.new(@panel, :label => 'Calculate')
my_radio = RadioBox.new(
  @panel,
  :label => "Select Conduit Shape",
  :choices => shape_choice,
  :major_dimension => 1
)
@panel_sizer = BoxSizer.new(VERTICAL)
@panel.set_sizer(@panel_sizer)

@panel_sizer.add(@y, 0, GROW|ALL, 2)
@panel_sizer.add(my_radio, 0, GROW|ALL, 2)
@panel_sizer.add(submit_button, 0, GROW|ALL, 2)
@panel_sizer.add(@result, 0, GROW|ALL, 2)

evt_button(submit_button.get_id()) {|cmd_event|

on_submit(cmd_event)}
evt_radiobox(my_radio.get_id()) {|cmd_event|
on_change_radio(cmd_event)}

show()

end

def on_change_radio(cmd_event)
@selected_shape = cmd_event.string
end

def on_submit(cmd_event)
y = @y.get_value().to_f
area = case
when @selected_shape == ‘Circular’ then Math::PI * y**2 / 4.0
when @selected_shape == ‘Rectangular’ then y * 5.0
else (5.0 + 2.0 * y) * y
end

@result.label = "#{area} square feet"

end
end

class MinimalApp < App
def on_init
MyFrame.new
end
end

MinimalApp.new.main_loop


#2

Jason L. wrote:

How do I organize widgets in a form when I need them placed in more than
a single column or row? I leaned how to use BoxSizer and successfully
displayed my widgets in a single column but can’t get the next column.

It sounds like you want either Wx::GridSizer or Wx::FlexGridSizer. The
latter allows for variable width columns or rows, so I generally find it
more useful.

There is also Wx::GridBagSizer, which allows cells to span rows or
columns, but I find nesting other simpler sizers easier to use than the
API for it.

alex


#3

Thank you for the pointer. I tried a simple example, doing my best to
read through wxWidgets examples and wxruby docs and - no success. I
created 4 buttons and they all show on top of each other. Can you see
anything I’m doing wrong? Thank you.

I’m doing this:

class MyFrame < Frame
def initialize
super(nil)
panel = Panel.new(self)
gs = FlexGridSizer.new(2,2,20,20)

b1 = Button.new(panel, :label=>"one")
b2 = Button.new(panel, :label=>"two")
b3 = Button.new(panel, :label=>"three")
b4 = Button.new(panel, :label=>"four")

gs.add(b1)
gs.add(b2)
gs.add(b3)
gs.add(b4)

gs.add_growable_row(1,1)
gs.add_growable_col(1,1)

show()

end
end

class MinimalApp < App
def on_init
MyFrame.new
end
end

MinimalApp.new.main_loop


#4

ah, I see. Thank you for that clarification. Just what I needed!


#5

Jason L. wrote:

Thank you for the pointer. I tried a simple example, doing my best to
read through wxWidgets examples and wxruby docs and - no success. I
created 4 buttons and they all show on top of each other. Can you see
anything I’m doing wrong? Thank you.

I’m doing this:

class MyFrame < Frame
def initialize
super(nil)
panel = Panel.new(self)
gs = FlexGridSizer.new(2,2,20,20)

b1 = Button.new(panel, :label=>"one")
b2 = Button.new(panel, :label=>"two")
b3 = Button.new(panel, :label=>"three")
b4 = Button.new(panel, :label=>"four")

gs.add(b1)
gs.add(b2)
gs.add(b3)
gs.add(b4)

gs.add_growable_row(1,1)
gs.add_growable_col(1,1)

show()

end
end

class MinimalApp < App
def on_init
MyFrame.new
end
end

MinimalApp.new.main_loop

Two things are not quite right. First, you don’t need the
‘add_growable_row’ etc as you have declared your grid to be 2x2. Also,
you have not told the panel about your sizer, so it does not know how to
layout your widgets. Change the middle part to:


gs.add(b1)
gs.add(b2)
gs.add(b3)
gs.add(b4)

# gs.add_growable_row(1,1) # delete this
# gs.add_growable_col(1,1) # delete this
panel.sizer = gs  # set the sizer

show()

You don’t need to create a separate panel to hold your widgets in, and
can instead add the widgets to ‘self’. Personally, I prefer to use
nested combinations of BoxSizers in most cases. The following example
may be helpful.


require ‘wx’

class BoxFrame < Wx::Frame
def initialize
super(nil, :title => “BoxSizers”)

# create two sub-sizers
left_sizer = Wx::BoxSizer.new Wx::VERTICAL
left_sizer.add(Wx::StaticText.new(self, Wx::ID_ANY, "Left side"))
left_sizer.add(Wx::Button.new(self, Wx::ID_ANY, "Button"))

right_sizer = Wx::BoxSizer.new Wx::VERTICAL
right_sizer.add(Wx::StaticText.new(self, Wx::ID_ANY, "Right side"))
right_sizer.add(Wx::Button.new(self, Wx::ID_ANY, "Button"))

# add left/right to main sizer with some padding
main_sizer = Wx::BoxSizer.new Wx::HORIZONTAL
main_sizer.add(left_sizer, 1, Wx::ALL, 10)
main_sizer.add(right_sizer, 1, Wx::ALL, 10)

set_sizer main_sizer

end
end

class GridFrame < Wx::Frame
def initialize
super(nil, :title => “FlexGridSizer”)

main_sizer = Wx::FlexGridSizer.new(2, 2, 10, 20)

main_sizer.add(Wx::StaticText.new(self, Wx::ID_ANY, "Left side"))
main_sizer.add(Wx::StaticText.new(self, Wx::ID_ANY, "Right side"))
main_sizer.add(Wx::Button.new(self, Wx::ID_ANY, "Left Button"))
main_sizer.add(Wx::Button.new(self, Wx::ID_ANY, "Right Button"))

set_sizer main_sizer

end
end

Wx::App.run do
BoxFrame.new.show
GridFrame.new.show
end

Hope that helps,

Peter.