Источник: http://docs.wxwidgets.org/3.1/overview_sizer.html
Сайзеры - особые объекты wxWidgets, служат для задания правил размещения контролов в диалогах и окнах wxWidgets.
Сайзеры являются наследниками класса wxSizer(и его потомков).
Понимание идеи и принципов применения сайзеров является ключевым при проектировании интерфейсов в wxWidgets.
Коэффициент растяжения (stretch factor): если сайзер содержит больше одного дочернего элемента, и ему предоставляется больше места, чем требуется его дочерним элементам вместе с их границами, возникает вопрос - как распределить избыточное место среди дочерних элементов. Для этого каждому дочернему элементу может быть назначен свой коэффициент растяжения, где значением по умолчанию является 0, означающий, что дочерний элемент не займет больше месте, чем запрошенный минимальный размер. Значение, большее чем ноль, интерпретируется по отношении к сумме всех коэффициентов растяжений дочерних элементов соответствующего сайзера, например, если для дочерних элемента получают коэффициент растяжения, равный 1, они займут по половине доступного места независимо от того, имел ли контрол минимальный размер меньший, чем другой. Следующий пример показывает диалог с тремя кнопками, у первой коэффициент растяжения равен
Сайзеры - особые объекты wxWidgets, служат для задания правил размещения контролов в диалогах и окнах wxWidgets.
Сайзеры являются наследниками класса wxSizer(и его потомков).
Понимание идеи и принципов применения сайзеров является ключевым при проектировании интерфейсов в wxWidgets.
Основные идеи
Алгоритм компоновки, используемый сайзерами wxWidgets, очень похож на алгоритмы, используемые в системах компоновке других пакетов GUI, таких, как AWT (Java), GTK или Qt. Алгоритм основан на идее индивидуальных вложенных саб-окон, сообщающих о своих минимально требуемых размерах и возможности растягиваться при изменении родительского окна. Чаще всего это означает, что программист не задает начальный размер диалога, для диалога скорее всего будет назначен сайзер, и этот сайзер будет запрошен о рекомендуемом размере. В свою очередь, сам сайзер запросит нужные данные у дочерних по отношению к нему элементов (которые могут быть обычными окнами, пустым пространством или другими сайзерами), таким образом будет построена иерархия сайзеров. Отметим, что wxSizer не наследован от wxWindow и поэтому не мешает упорядочению вкладок и и требует очень мало ресурсов по сравнению с реальным экранным окном..
Что делает сайзеры хорошо пригодными для использования в wxWidgets, так это то, что каждый контрол сообщает собственный минимальный размер и алгоритм может без проблем обрабатывать различия в размерах шрифтов или различия в размерах окон (элементов диалогов) на различных платформах. К примеру, если стандартный шрифт а также общий дизайн контролов в Linux/GTK требует больше места по сравнению с Windows, то начальный размер диалога в Linux/GTK автоматически будет больше, чем в Windows.
В настоящее время в wxWidgets есть семь разных видов сайзеров. Каждый из них представляет собой собой отдельный способ выравнивания элементов диалога или выполняет особую задачу, такую, как выравнивание статических поля вокруг элемента диалога (или другого сайзера). Эти сайзеры будут последовательно рассмотрены далее. Дополнительную информацию о том, как использовать сайзеры в коде, можно посмотреть в разделе wxBoxSizer.
Общие свойства
Все сайзеры являются контейнерами, то есть они используются для выравнивания положения одного элемента диалога (или нескольких элементов диалога), которые содержатся в этом контейнере. Такие элементы иногда называются дочерними элементами сайзера. Независимо от того, как отдельный сайзер размещает дочерние элементы, все дочерние элементы имеют общие свойства:
Минимальный размер (minimal size): минимальны размер обычно идентичен начальному размеру контрола, и может либо установлен явно с помощью поля wxSize в конструкторе контрола, или может быть рассчитано самой wxWidgets, обычно путем установки значений высоты и ширины элемента в -1. Отметим, что только некоторые контролы могут рассчитать свой размер (такие как черкбокс):
Другие (такие, как листбокс) не имеют значения ширины и высоты по умолчанию и поэтому требут указания реальных размеров.
Некоторые контролы могут рассчитать свою высоту, но не ширину (например, контрол "однострочный текст):
Граница (border): граница - это всего лишь пустой пространство, используется для разделения элементов диалога между собой. Граница может быть как полностью вокруг контрола, так и в любой комбинации из сторон, например только сверху и снизу. Толщина границы по умолчанию обычно равна 5 пикселям. Следующие примеры показывают диалоги с одним элементом диалога (кнопкой) и границей в 0, 5, и 10 пикселей:
Выравнивание(alignment): довольно часто для элемента диалога отводится больше места, его минимальный размер плюс размер границы. В зависимости от того, какой флаг используется в данном элементе диалога, этот элемент может заполнить все доступное пространство, например, он может увеличиться до величины большей, чем минимальный размер, или он может быть перемещен в центр доступного пространства или даже вбок . Следующий пример показывает лисбокс и три кнопки в горизонтальном бокссайзере; одна кнопка в центре, вторая выровнена вверх, еще одна выровнена вниз:
1, и она растягивается, тогда как у двух других этот коэффициент равен 0, и их ширина не изменилась
:Прячем контролы с помощью сайзеров
Контролы, помещенные в сайзеры, могут быть скрыты точно так же, как и любые другие контролы с помощью метода wxWindow::Show(). Однако, у wxSizer есть еще один метод, который сообщает сайзеру, что данный контрол не нужно учитывать при вычислении размеров. Чтобы спрятать окно с помощью сайзеров, вызываем wxSizer::Show(). Затем следует вызвать Layout для сайзера, чтобы изменения были приняты.
Сие полезно, если нужно прятать части интерфейса, поскольку позволяет избегать необходимости лишний раз удалять и добавлять контролы в сайзер.
- Замечание
- Такое поддеривается только в wxBoxSizer и в wxFlexGridSizer.
wxBoxSizer
wxBoxSizer может размещать дочерние элементы либо вертикально, либо горизонтально, в зависимости от установленного флага в конструкторе. При использовании вертикального сайзера, каждый дочерний элемент может быть отцентрирован или выровнен вправо или влево. Соответственно, при использовании горизонтального сайзера, каждый дочерний элемент может быть выровнен по центру, по верху или по низу. Коэффициент растяжения, описанный в последнем параграфе, используется для основной ориентации, то есть когда используется горизонтальный бокссайзер, каэффициент растяжения определяет, насколько сильно могут быть растянуты дочерние элементы по гоизонтали. В следующем примере показывается диалог из предыдущего примера, только бокссайзер теперь вертикальный:
wxStaticBoxSizer
wxGridSizer
wxGridSizer - это двумерный сайзер. Все дочерние элементы получают одинаковый размер, равный минимальному размеру, необходимому самому большому из дочерних элементов, в данном случае - полю текстового ввода в левом нижнем углу. В гридсайзере фиксировано либо число столбцов, либо число строк. При добавлении дочерних элементов грисайзер будет расти в другой (незафиксированной) ориентации:
wxFlexGridSizer
wxFlexGridSizer - это двумерный сайзер, производный от сайзера wxGridSizer. Ширина каждого столбца и высота каждой строки вычисляются отдельно, в соответствии с минимальными требованиями размеров самого большого дочернего элемента. Дополнительно, строки и столбц могут быть объявлены растяжимыми, если сайзеру назначен размер, отличающийся от того, который он запросил. На следующем примере показан тот же самый диалог, что и выше, но с использованием флексгридсайзера:
Другие типы сайзеров
wxStdDialogButtonSizer - это сайзер, который размещает в диалоге кнопку, в соответствии со стандартами размещения и кнопок и последовательностью, определяемой платформой или настройками пользовательского инструментария, если таковые имеются. Для удобства при создании такого сайзера можно воспользоваться методом wxDialog::CreateButtonSizer().
wxWrapSizer - сайзер, который размещает свои элементы в одну линию, например, в бокссайзере – пока в этом направлении есть доступное место. При исчерпании свободного места, добавляется новая строка, и новые элементы будут добавляться уже в нее.
wxGridBagSizer - довольно специальный вид сайзера, который, в отличии от других классов сайзеров, позволяет помещать элементы в указанную позицию.
Программирование с применением wxBoxSizer
Основная идей бокссайзера wxBoxSizer заключается в том, что чаще всего окна конструируются в достаточно простой базовой геометрии, как правило в строке или в столбце или в нескольких иерархиях.
В качестве примера, сконструируем диалог, который будет содержать текстовое поле в верхней части и две кнопки в нижней части. Это может рассматриваться как иерархическая структура "сверху-вниз" с текстом в верхней строке и двумя кнопками в нижней строке: кнопка OK слева кнопка Cancel справа. Во многих случаях (особенно в диалогах под Unix и в обычных окнах) главное окно может растягиваться пользователем, и это изменение распространяется на дочерние элементы. В нашем случае мы хотим, чтобы текстовая область увеличивалась при увеличении диалога, а кнопки оставить фиксированного размера. Дополнительно, вокруг всех контролов будет такая граница, чтобы диалог выглядел симпатично и - (ложка дегтя) - чтобы кнопки центрировались по мере изменения ширины диалога.
Это - уникальная особенность бокссайзера, который может увеличиваться в обоих направлениях (в высоту и в ширину), но может распределять свой рост в главном направлении (в горизонтальном для строки) неравномерно среди своих дочерних элементов. В нашем примере, вертикальный сайзер должен распространять все изменения по высоте только на текстовую область, но не на область кнопок. Это определяется параметром "пропорционально"(proportion) при добавлении окна (или другого сайзера ) в сайзер. Он интерпретируется как весовой коэффициент, то есть он может быть равен нулю, это означает, что окно вообще не может менять размеры, или больше нуля. Если несколько окон имеет значение больше нуля, значение интерпретируется относительно суммы всех весовых коэффициентов сайзера, поэтому при добавлении двух окон со значением равным
1
, они будут оба растягиваться одинаково, и в каждой половине у них будут одинаковые размеры дополнительного пространства. Но что же тогда делать, если сайзер столбца меняет свою ширину? Это поведение управляется флагами(flags) (второй параметр функции Add()): флаг Ноль или Нет означает, что окно будет сохранять оригинальный размер , флаг wxGROW
(то же самое, что и wxEXPAND
) заставит окно расти до размеров сайзера, флаг wxSHAPED
сообщает окну, что нужно менять размер пропорционально , сохраняя исходный коэффициент растяжения. Если флаг wxGROW
не используется, то элемент может быть выровнен внутри свободного пространства.
Флаги
wxALIGN_LEFT
, wxALIGN_TOP
, wxALIGN_RIGHT
, wxALIGN_BOTTOM
, wxALIGN_CENTER_HORIZONTAL
и wxALIGN_CENTER_VERTICAL
делает то, чем они называются. Флаг wxALIGN_CENTRE
(то же самое, что и wxALIGN_CENTER
) определяется как (wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL
). Выравнивание по умолчанию - это wxALIGN_LEFT | wxALIGN_TOP
.
Как упоминалось выше, любое окно, принадлежащее сайзеру, может иметь границу, и дополнительно можно указывать, какие из четырех сторон могут иметь эту границу, с помощью констант
wxTOP
, wxLEFT
, wxRIGHT
и wxBOTTOM, или
wxALL в случае, когда граница со всех сторон (можно также вместо них использовать wxNORTH
, wxWEST
и т.д.). Эти флаги могут использоваться в комбинации с вышеупомянутыми флагами выравнивания в качестве второго аргумента метода Add() с использованием бинарного оператора "или" - |. Также должна быть известна граница сайзера, которая задается третьим параметром метода Add(). Имеется в виду, что полное поведение сайззера и их дочерних элементов может контролироваться тремя параметрами методами Add().
// Строим диалог, который растягивается вместе с текстом в верхней части,
// и нерастягиваемой частью с двумя кнопками в нижней части.
{
// Создаем текстовый контрол с минимальным размером 100x60
topsizer->Add(
1, // Делаем вертикальное растягивание
wxALL, // делаем границу вокруг
10 ); // Устанавливаем ширину границы, равную 10
button_sizer->Add(
0, // Горизонтально нерастягиваемый
wxALL, // Кругом границы (неявное выравнивание по верху)
10 ); // Устанавливаем ширину границы, равную 10
button_sizer->Add(
0, // Горизонтально нерастягиваемый
10 ); // Устанавливаем ширину границы, равную 10
topsizer->Add(
button_sizer,
0, // Вертикально нерастягиваемый
wxALIGN_CENTER ); // Без бордюра, горизонтальная центровкаhorizontally
SetSizerAndFit(topsizer); // Используем этот сайзер для подгонки размеров окна
// и предотвращения от его слишком сильного уменьшения
Заметьте, что рекомендуемым методом для указания флагов для wxSizer является использование wxSizerFlags. Этот класс значительно облегчает процесс задания флагов в wxSizer.
Вот так предыдущий пример можно было бы реализовать с помощью wxSizerFlags:
// Строим диалог, который растягивается вместе с текстом в верхней части,
// и нерастягиваемой частью с двумя кнопками в нижней части.
{
// Создаем текстовый контрол с минимальным размером 100x60
// Вертикальное растягивание, с бордюром шириной 10
topsizer->Add(
wxSizerFlags(1).Align().Expand().Border(wxALL, 10));
//Создаем две кнопки, нерастягиваемые горизонтально
// с бордюром вокруг, ширина бродюра 10 и верхним выравниванием по умолчанию
button_sizer->Add(
wxSizerFlags(0).Align().Border(wxALL, 10));
button_sizer->Add(
wxSizerFlags(0).Align().Border(wxALL, 10));
//Создаем сайзер без бордюра, центрированный по горизонтали
topsizer->Add(
button_sizer,
wxSizerFlags(0).Center() );
SetSizerAndFit(topsizer); // Используем этот сайзер для подгонки размеров окна
// и предотвращения от его слишком сильного уменьшения
}
Комментариев нет:
Отправить комментарий