понеділок, 21 вересня 2009 р.

wxRuby → Сайзери (3 частина)

У попередній частині ми розглянули Wx::BoxSizer. Продовжимо знайомитися з сайзерами wxRuby.



Wx::StaticBoxSizer
Клас Wx::StaticBoxSizer є похідним від Wx::BoxSizer і відрізняється від нього тільки тим, що цей сайзер поміщає свої дочірні елементи в рамку з надписом, яка являє собою екземпляр класу Wx::StaticBox.
Використання Wx::StaticBoxSizer практично нічим не відрізняється від використання класу Wx::BoxSizer за виключенням того, що конструктор цього класу вимагає ще один параметр - екземпляр класу Wx::StaticBox, який і буде обводити дочірні елементи сайзера.

Wx::StaticBoxSizer.new(Wx::StaticBox box,  Integer orient)


Wx::StaticBoxSizer.new(Integer orient,  Wx::Window parent,
String label = '')


Перший приклад конструктора використовує вже існуючий екземпляр класу Wx::StaticBox. Він бере пов'язаний Wx::StaticBox та орієнтацію(параметр orient), яка може бути горизонтальною або вертикальною. Другий конструктор створює новий Wx::StaticBox із вказаними надписом і батьківським вікном.

Розглянемо простий приклад Wx::StaticBoxSizer разом з двома кнопками.
  def do_sizer
static_box = Wx::StaticBox.new(self, :label => "StaticBox")
sizer = Wx::StaticBoxSizer.new(static_box, Wx::VERTICAL)

button1 = Wx::Button.new(self, :label => 'Button 1')
button2 = Wx::Button.new(self, :label => 'Button 2')

sizer.add_item(button1)
sizer.add_item(button2)

set_sizer(sizer)
end


У цьому прикладі ми спочатку створили екземпляр класу Wx::StaticBox, а потім сайзер Wx::StaticBoxSizer, в конструктор якого і передали щойно створений Wx::StaticBox, а також дві кнопки.

В результаті такого розміщення елементів ми отримали вікно, яке виглядає наступним чином:


Зверніть увагу, що Wx::StaticBox займає все вікно, так як він є основним сайзером для вікна. Якщо в перший Wx::StaticBoxSizer вставити дочірні такі ж сайзери, то вони будуть обводити тільки елементи керування. Давайте додамо ще пару кнопок:
  def do_sizer
static_box0 = Wx::StaticBox.new(self, :label => "StaticBox 0")
vert_sizer = Wx::StaticBoxSizer.new(static_box0, Wx::VERTICAL)

static_box1 = Wx::StaticBox.new(self, :label => "StaticBox 1")
static_box2 = Wx::StaticBox.new(self, :label => "StaticBox 2")

sizer_1 = Wx::StaticBoxSizer.new(static_box1, Wx::HORIZONTAL)
sizer_2 = Wx::StaticBoxSizer.new(static_box2, Wx::HORIZONTAL)

vert_sizer.add(sizer_1)
vert_sizer.add_item(sizer_2, :flag => Wx::ALIGN_RIGHT|Wx::ALIGN_BOTTOM)

button1 = Wx::Button.new(self, :label => 'Button 1')
button2 = Wx::Button.new(self, :label => 'Button 2')
button3 = Wx::Button.new(self, :label => 'Button 3')
button4 = Wx::Button.new(self, :label => 'Button 4')

sizer_1.add_item(button1)
sizer_1.add_item(button2)

sizer_2.add_item(button3)
sizer_2.add_item(button4)

set_sizer(vert_sizer)
end


Тут ми створили три екземпляри класу Wx::StaticBoxSizer і передали кожному по своєму екземпляру класу Wx::StaticBox. В перший вертикальний сайзер ми додали ще два горизонтальні сайзери(sizer_1 та sizer_2). Перший буде прив'язаний по замовчуванню до лівого краю, а другий ми перенесли в правий нижній кут, вказавши прапорці Wx::ALIGN_RIGHT і Wx::ALIGN_BOTTOM. Насправді прапорець Wx::ALIGN_BOTTOM не буде відігравати тут ніякої ролі, оскільки друга "полиця" vert_sizer по висоті буде обмежена саме цим другим сайзером sizer_2. Але цей прапорець дасть нам зрозуміти істинні розміри головного сайзера vert_sizer, тому що розмір його рамки може ввести в оману.
В результаті виконання цього прикладу ми побачимо:


Для більшої наочності приведу знімок вікна з ОС Windows:


І щоб було більш зрозуміло, те ж вікно з намальованими сайзерами:


Як бачите, вкладені сайзери зайняли не всю доступну область, на відміну від головного сайзера vert_sizer.
На цьому огляд Wx::StaticBoxSizer закінчимо і перейдемо до огляду інших сайзерів.

Wx::GridSizer
Wx::GridSizer розміщує елементи керування (або дочірні сайзери) в комірках віртуальної таблиці. Віртуальної, тому що насправді ніякої таблиці не створюється. Розміри всіх комірок у цій таблиці однакові як по ширині, так і по висоті. При цьому розміри комірок залежать від того чи використовується прапорець Wx::EXPAND для розтягнення сайзера до максимально можливих розмірів. У випадку якщо Wx::EXPAND не використовується, ширина кожної комірки рівна ширині найбільш широкого елементу керування, а висота, відповідно, рівна висоті найбільш високого. Якщо при додаванні сайзера був встановлений прапорець Wx::EXPAND (або сайзер є головним для вікна), то вся займана сайзером площа ділиться порівну на кількість рядків і стовпців, необхідних для розміщення елементів.
Для початку розглянемо конструктор Wx::GridSizer:
GridSizer.new(Integer rows,  Integer cols,  Integer vgap,
Integer hgap)


GridSizer.new(Integer cols,  Integer vgap = 0,
Integer hgap = 0)


Він приймає 4 параметри. rows і cols визначає кількість рядків і стовпців у сайзері. Якщо який-небудь з цих параметрів рівний нулю, то він буде розрахований виходячи із загальної кількості дочірніх елементів у сайзері, роблячи сайзер динамічно зростаючим. vgap і hgap - величина зазору між рядками і стовпцями у пікселях, відповідно.

Розглянемо приклади. Нехай спочатку Wx::GridSizer буде основним для вікна. Розмістимо 6 кнопок у два рядки і три стовпці:
  def do_sizer
grid_sizer = Wx::GridSizer.new(cols = 3, rows = 2)
6.times do |i|
button = Wx::Button.new(self, :label => "Button #{i}")
grid_sizer.add(button)
end
set_sizer(grid_sizer)
end
end




Так як основний сайзер намагається зайняти якомога більшу область вікна, то у нашому випадку grid_sizer займе все вікно, а висота рядків буде рівна висоті клієнтської області вікна, поділеної на кількість рядків. Аналогічно з шириною комірок, вона буде рівна ширині клієнтської області вікна, поділеної на кількість стовпців, необхідних для розміщення дочірніх елементів.


У цьому прикладі ми явно задали кількість рядків і стовпців за допомогою конструктора Wx::GridSizer, але ми би добилися того ж результату, якщо б вказали тільки кількість стовпців, які ми хочемо отримати. У цьому випадку сайзер сам розрахує необхідну кількість рядків. Пізніше ми розглянемо і такий приклад.
А щоб переконатися в тому, що комірки сайзера дійсно займають той розмір, який ми тільки що бачили на малюнку, розтягнемо кожну кнопку на всю комірку за допомогою прапорця Wx::EXPAND.
  def do_sizer
grid_sizer = Wx::GridSizer.new(cols = 3, rows = 2)
6.times do |i|
button = Wx::Button.new(self, :label => "Button #{i}")
grid_sizer.add_item(button, :flag => Wx::EXPAND)
end
set_sizer(grid_sizer)
end


І побачимо очікуваний результат:


Наступні експерименти з цим сайзером ми будемо проводити, коли комірки сайзера залежать від розміру елементів керування, які вона містить. Тому підготуємо наступний приклад, у якому Wx::GridSizer не буде розтягуватися на все вікно, а буде знаходитися всередині сайзера Wx::BoxSizer.
  def do_sizer
box_sizer = Wx::BoxSizer.new(Wx::VERTICAL)
grid_sizer = Wx::GridSizer.new(cols = 3, rows = 2)

button_list = Array.new(6) {|i| Wx::Button.new(self, :label => "Button #{i}")}

button_list.each do |button|
grid_sizer.add_item(button)
end

box_sizer.add(grid_sizer)
set_sizer(box_sizer)
end


У цьому прикладі для зручності кнопки створюються заздалегідь і поміщаються у масив, щоб в майбутньому ми могли незалежно одна від одної змінювати їх властивості. Основним тут є box_sizer, а grid_sizer "приклеєний" до верхнього лівого кута. Якщо ми запустимо цей скрипт, то побачимо таке розташування кнопок:


Як і варто було очікувати, розміри комірок однакові і співпадають із розмірами кнопок.

А тепер змінимо мінімально можливий розмір однієї кнопки і подивимося як зміняться розміри комірок таблиці:
  def do_sizer
box_sizer = Wx::BoxSizer.new(Wx::VERTICAL)
grid_sizer = Wx::GridSizer.new(cols = 3, rows = 2)

button_list = Array.new(6) {|i| Wx::Button.new(self, :label => "Button #{i}")}
button_list[0].set_min_size([100, 35])

button_list.each do |button|
grid_sizer.add_item(button)
end

box_sizer.add(grid_sizer)
set_sizer(box_sizer)
end




Всі розміри комірок знову рівні, але на цей раз співпадають з розміром найбільшої кнопки "Button 0". Таблицю комірок сайзера у цьому випадку можна намалювати наступним чином:


В наступному прикладі розтягнемо всі кнопки за допомогою прапорця Wx::EXPAND, щоб переконатися, що розміри комірок саме такі, як ми їх представляли:
  def do_sizer
box_sizer = Wx::BoxSizer.new(Wx::VERTICAL)
grid_sizer = Wx::GridSizer.new(cols = 3, rows = 2)

button_list = Array.new(6) {|i| Wx::Button.new(self, :label => "Button #{i}")}
button_list[0].set_min_size([100, 35])

button_list.each do |button|
grid_sizer.add_item(button, :flag => Wx::EXPAND)
end

box_sizer.add(grid_sizer)
set_sizer(box_sizer)
end




Тепер розглянемо параметри vgap і hgap, які задають відстань між елементами керування. Найпростіше ці параметри уявити у вигляді товщини стінок, які розділяють елементи, але при цьому зовнішні стінки сайзера-таблиці залишаються нульової товщини.

У наступному прикладі ми додамо 10 пікселів відстані між рядками і 20 пікселів між стовпцями:
  def do_sizer
box_sizer = Wx::BoxSizer.new(Wx::VERTICAL)
grid_sizer = Wx::GridSizer.new(rows = 2, cols = 3, vgap = 10, hgap = 20)

button_list = Array.new(6) {|i| Wx::Button.new(self, :label => "Button #{i}")}

button_list.each do |button|
grid_sizer.add_item(button)
end

box_sizer.add(grid_sizer)
set_sizer(box_sizer)
end


В результаті отримаємо:


Схожого ефекту можна було б досягнути, використовуючи прапорці, які додають рамку(border) навкруги елементу: Wx::TOP, Wx::BOTTOM, Wx::LEFT, Wx::RIGHT і Wx::ALL, але в даному випадку використовувати параметри vgap і hgap зручніше, інакше довелось би для кожної кнопки індивідуально вказувати з якої сторони повинна бути рамка. Крім того, рамка змінила б розміри комірок.

У попередніх приклад ми явно задавали кількість рядків і стовпців таблиці, але ж, знаючи кількість елементів і кількість бажаних стовпців, Wx::GridSizer може сам розраховувати кількість необхідних рядків. Давайте розглянемо як він це буде робити:
  def do_sizer
box_sizer = Wx::BoxSizer.new(Wx::VERTICAL)
grid_sizer = Wx::GridSizer.new(cols = 2)

count = 1

button_list = Array.new(count) {|i| Wx::Button.new(self, :label => "Button #{i}")}

button_list.each do |button|
grid_sizer.add_item(button)
end

box_sizer.add(grid_sizer)
set_sizer(box_sizer)
end


У цьому прикладі ми будемо змінювати кількість кнопок від 1 до 5, і за допомогою зміни значення змінної count.
count = 1

Нічого цікавого, одна кнопка вона і є одна кнопка.

count = 2

Тепер вже сайзер може зайняти два стовпці, що він і робить. У нас виходить один рядок.

count = 3

У нас з'являється другий рядок, але зверніть увагу на те, що спочатку заповнюється перший стовпчик, а потім другий.

count = 4

Ну і на кінець ми заповнили два стовпчика, і в нас з'явилося два рядки.

сount = 5

Можна і далі збільшувати значення змінної count - кількість рядків буде збільшуватися, але завжди в першу чергу буде повністю заповнюватися спочатку перший стовпчик, а потім другий.

Мабуть, це всі основні особливості класу Wx::GridSizer, давайте перейдемо до розгляду наступного сайзера.


Wx::FlexGridSizer
Wx::FlexGridSizer по поведінці схожий на Wx::GridSizer, він також розміщує елементи керування в комірках таблиці, але, на відміну від Wx::GridSizer у Wx::FlexGridSizer рядки і стовпці можуть розтягуватися, щоб займати весь вільний простір по вертикалі чи горизонталі.

Конструктор класу Wx::FlexGridSizer нічим не відрізняється від конструктора Wx::GridSizer:
Wx::FlexGridSizer.new(Integer rows,  Integer cols,  Integer vgap,
Integer hgap)

Wx::FlexGridSizer.new(Integer cols,  Integer vgap = 0,
Integer hgap = 0)


Для того щоб скористатися особливостями цього сайзера і встановити, які рядки і стовпці повинні розтягуватись передбачено, відповідно, два методи:
Wx::FlexGridSizer#add_growable_row(Integer idx,  Integer proportion = $0$)

Wx::FlexGridSizer#add_growable_col(Integer idx,  Integer proportion = $0$)


Ці методи приймають 2 параметри:
idx - номер рядка або стовпчика, починаючи з 0-ого, який повинен розтягуватись
proportion - пропорції, які визначають як потрібно розподілити вільне місце між розтяжними рядками і стовпцями. Цей параметр грає ту ж роль, що і однойменний параметр методу add().

Розглянемо цю поведінку на прикладах.
Для початку створимо Wx::FlexGridSizer, який не має розтяжних рядків і стовпців. У цьому випадку всі комірки мають мінімально можливий розмір, навіть не дивлячись на те, що сайзер встановлений як основний для вікна.
  def do_sizer
grid_sizer = Wx::FlexGridSizer.new(cols = 2)

count = 4

button_list = Array.new(count) {|i| Wx::Button.new(self, :label => "Button #{i}")}

grid_sizer.add_item(button_list[0])
grid_sizer.add_item(button_list[1])
grid_sizer.add_item(button_list[2])
grid_sizer.add_item(button_list[3])

set_sizer(grid_sizer)
end




А тепер змінимо приклад так, щоб другий стовпчик був "тягучим".
  def do_sizer
grid_sizer = Wx::FlexGridSizer.new(cols = 2)
grid_sizer.add_growable_col(1)

count = 4

button_list = Array.new(count) {|i| Wx::Button.new(self, :label => "Button #{i}")}

grid_sizer.add_item(button_list[0])
grid_sizer.add_item(button_list[1], :flag => Wx::EXPAND)
grid_sizer.add_item(button_list[2])
grid_sizer.add_item(button_list[3], :flag => Wx::ALIGN_RIGHT|Wx::ALIGN_BOTTOM)

set_sizer(grid_sizer)
end




У цьому прикладі ми за допомогою виклику методу grid_sizer.add_growable_col(1) вказуємо, що другий стовпчик (перший рахується нульовим) повинен розтягнутися так, щоб зайняти вільне місце. Щоб переконатися у цьому, ми другу кнопку(button_list[1]) розтягуємо на всю комірку за допомогою прапорця Wx::EXPAND, а останню кнопку вирівнюємо по правому краю (Wx::ALIGN_RIGHT) і нижньому краю (Wx::ALIGN_BOTTOM). У даному випадку вирівнювання по нижньому краю нічого не дасть, так як розтягується тільки другий стовпчик, а не рядок, але завдяки цьому ми ще раз переконалися, що вертикальний розмір рядка не змінився.

Тепер розглянемо розтягування рядків.
  def do_sizer
grid_sizer = Wx::FlexGridSizer.new(cols = 2)
grid_sizer.add_growable_row(1)

count = 4

button_list = Array.new(count) {|i| Wx::Button.new(self, :label => "Button #{i}")}

grid_sizer.add_item(button_list[0])
grid_sizer.add_item(button_list[1])
grid_sizer.add_item(button_list[2], :flag => Wx::EXPAND)
grid_sizer.add_item(button_list[3], :flag => Wx::ALIGN_RIGHT|Wx::ALIGN_BOTTOM)

set_sizer(grid_sizer)
end


У цьому прикладі за допомогою виклику метода grid_sizer.add_growable_row(1) ми вказуємо, що другий рядок повинен розтягуватись. На цей раз розтягуватись на всю комірку буде кнопка button_list[2], а прапорці для button_list[3] залишаться ті самі. І у результаті отримаємо:


Крім того для одного сайзера можна вказати, декілька розтяжних рядків і(або) стовпців. У наступному прикладі ми створимо 6 кнопок, розміщених у два рядки і три стовпці, і вкажемо, що останні два стовпці повинні розтягуватися. Для кнопок, які повинні потрапити у ці два стовпці ми встановимо прапорець Wx::EXPAND, щоб розтягнути їх на всю комірку.
  def do_sizer
grid_sizer = Wx::FlexGridSizer.new(cols = 3)
grid_sizer.add_growable_col(1)
grid_sizer.add_growable_col(2)

count = 6

button_list = Array.new(count) {|i| Wx::Button.new(self, :label => "Button #{i}")}

grid_sizer.add_item(button_list[0])
grid_sizer.add_item(button_list[1], :flag => Wx::EXPAND)
grid_sizer.add_item(button_list[2], :flag => Wx::EXPAND)
grid_sizer.add_item(button_list[3])
grid_sizer.add_item(button_list[4], :flag => Wx::EXPAND)
grid_sizer.add_item(button_list[5], :flag => Wx::EXPAND)

set_sizer(grid_sizer)
end




В даному випадку розтяжні стовпці поділити порівну доступне їм вільне місце. Щоб змінити співвідношення вільного місця між стовпчиками змінимо значення параметрів proportion. В наступному прикладі співвідношення останніх двох стовпців буде рівне 1:3.
  def do_sizer
grid_sizer = Wx::FlexGridSizer.new(cols = 3)
grid_sizer.add_growable_col(1, proportion = 1)
grid_sizer.add_growable_col(2, proportion = 3)

count = 6

button_list = Array.new(count) {|i| Wx::Button.new(self, :label => "Button #{i}")}

grid_sizer.add_item(button_list[0])
grid_sizer.add_item(button_list[1], :flag => Wx::EXPAND)
grid_sizer.add_item(button_list[2], :flag => Wx::EXPAND)
grid_sizer.add_item(button_list[3])
grid_sizer.add_item(button_list[4], :flag => Wx::EXPAND)
grid_sizer.add_item(button_list[5], :flag => Wx::EXPAND)

set_sizer(grid_sizer)
end




І останній для цього розділу приклад показує, що на деякі комірки може припадати пересічення розтяжних рядків і стовпців.
  def do_sizer
grid_sizer = Wx::FlexGridSizer.new(cols = 2)
grid_sizer.add_growable_col(1)
grid_sizer.add_growable_row(1)

count = 4

button_list = Array.new(count) {|i| Wx::Button.new(self, :label => "Button #{i}")}

grid_sizer.add_item(button_list[0])
grid_sizer.add_item(button_list[1])
grid_sizer.add_item(button_list[2], :flag => Wx::ALIGN_BOTTOM)
grid_sizer.add_item(button_list[3], :flag => Wx::EXPAND)

set_sizer(grid_sizer)
end


В результаті бачимо, остання кнопка, яка опинилася на пересічені розтяжних стовпчика і рядка значно додала у розмірах: 



Wx::GridBagSizer
Wx::GridBagSizer, як і два попередніх сайзера розставляє елементи керування в комірках таблиці. Відмінність полягає у тому, що, на відміну від попередніх сайзерів, цей сайзер не розраховує кількість стовпчиків виходячи з кількості рядків, а при додаванні елементу програміст повинен явно вказати у яку комірку він хоче помістити елемент. Крім того один елемент керування може займати відразу декілька комірок. Всі комірки при цьому мають однаковий розмір, а сам сайзер не розтягується на все вікно, його комірки завжди мають мінімально можливий розмір.
Конструктор Wx::GridBagSizer має наступний вигляд:
Wx::GridBagSizer.new(Integer vgap = 0,  Integer hgap = 0)


У ньому ми не можемо задати кількість рядків і стовпців, ми можемо вказати тільки зазори між рядками і стовпцями сайзера.Метод add() цього сайзера теж змінився:
Wx::SizerItem add(Wx::Window window,  GBPosition pos,
Wx::GBSpan span = DefaultSpan,
Integer flag = 0,
Integer border = 0,
Object userData = nil)

Wx::SizerItem add(Wx::Sizer sizer,  Wx::GBPosition pos,
Wx::GBSpan span = DefaultSpan,
Integer flag = 0,
Integer border = 0,
Object userData = nil)

Wx::SizerItem add(Integer width,  Integer height,
Wx::GBPosition pos,
Wx::GBSpan span = DefaultSpan,
Integer flag = 0,
Integer border = 0,
Object userData = nil)

Wx::SizerItem add(GBSizerItem item)


В ньому додалося два параметри:
pos визначає в яку комірку повинен додаватися елемент. Цей параметр повинен бути екземпляром класу Wx::GBPosition.
Wx::GBPosition.new(Integer row,  Integer col)

span визначає скільки комірок по горизонталі і вертикалі повинен займати елемент, що додається. Цей параметр повинен бути екземпляром класу Wx::GBSpan.
GBSpan.new(Integer rowspan,  Integer colspan)

(1, 1) - значення по замовчуванню, яке означає, що елемент буде займати одну комірку у будь-якому напрямку.

Зауважте, що ми ніде не вказуємо ні загальної кількості рядків, ні загальної кількості стовпчиків. Вони обчислюються виходячи із розташування доданих елементів.
В якості прикладу для початку отримаємо таке розміщення кнопок у вікні:


Ми могли б отримати таке розміщення використовуючи сайзер Wx::GridSizer, якщо б деякі комірки заповнили порожніми місцями (додали б екземпляри класу Wx::Size), але в Wx::GridBagSizer це реалізувати простіше:
  def do_sizer
grid_sizer = Wx::GridBagSizer.new()

count = 4

button_list = Array.new(count) {|i| Wx::Button.new(self, :label => "Button #{i}")}

grid_sizer.add(button_list[0], pos = Wx::GBPosition.new(0, 1))
grid_sizer.add(button_list[1], pos = Wx::GBPosition.new(1, 0))
grid_sizer.add(button_list[2], pos = Wx::GBPosition.new(1, 2))
grid_sizer.add(button_list[3], pos = Wx::GBPosition.new(2, 1))

set_sizer(grid_sizer)
end


При додаванні кнопки в сайзер ми просто вказуємо куди саме її необхідно помістити. На наступному малюнку показане те саме вікно з намальованою таблицею сайзера:


Тепер скористаємося особливостями цього сайзера і зробимо так, щоб кнопки зайняли би не одну, а дві комірки віртуальної таблиці:


Для цього під час додавання нульової і другої кнопки вкажемо скільки комірок вони повинні займати в обох напрямках за допомогою параметра span:
  def do_sizer
grid_sizer = Wx::GridBagSizer.new()

count = 4

button_list = Array.new(count) {|i| Wx::Button.new(self, :label => "Button #{i}")}

grid_sizer.add(button_list[0], pos = Wx::GBPosition.new(0, 1),
span = Wx::GBSpan.new(1, 2),
flag = Wx::EXPAND)
grid_sizer.add(button_list[1], pos = Wx::GBPosition.new(1, 0),
span = Wx::GBSpan.new(1, 1),
flag = Wx::EXPAND)
grid_sizer.add(button_list[2], pos = Wx::GBPosition.new(1, 2),
span = Wx::GBSpan.new(2, 1),
flag = Wx::EXPAND)
grid_sizer.add(button_list[3], pos = Wx::GBPosition.new(2, 1),
span = Wx::GBSpan.new(1, 1),
flag = Wx::EXPAND)

set_sizer(grid_sizer)
end


Як бачите все доволі просто. У цьому прикладі ми розтягнули всі кнопки (навіть ті, на які цей прапорець не подіє), щоб показати, що кнопки дійсно можуть зайняти не тільки свою, а й сусіді комірки. У цьому прикладі для наочності використовуються параметри span, навіть для тих, що для них залишене значення по замовчуванню.

Для наочності на наступному малюнку те ж саме вікно, але з намальованим сайзером:


Ось ми і розглянули всі існуючі в wxRuby сайзери, а заодно і навчилися ними користуватися.

Основою для написання цієї і попередніх частин(1, 2) стала стаття Сайзеры в wxWidgets / wxPython

На все добре і успіхів.

Немає коментарів: