Руководство по программированию с wxWidgets (4. Управление компоновкой в wxWidgets.

Jan Bodnar, “The wxWidgets programming tutorial (4. Layout management in wxWidgets)”, public translation into Russian from English More about this translation.

Translate into another language.

Управление компоновкой в wxWidgets.

Стандартное приложение состоит из различный виджетов. Эти виджеты расположены внутри контейнера виджетов. Программист должен уметь управлять компоновкой этих элементов в окне программы. Это не простая задача. В wxWidgets существует два способа её осуществления.

* absolute positioning (абсолютное позиционирование)

* sizers (классификаторы)

Абсолютное позиционирование.

Программист задаёт позицию и размер для каждого виджета в пикселях. Если вы используете абсолютное позиционирование, то должны помнить несколько вещей:

* размер и позиция виджета не изменятся, если вы измените размеры окна

* приложения будут выглядеть на разных платформах по-разному и достаточно паршиво.

* изменение шрифта в приложении может испортить компоновку элементов окна

* если вы решите изменить компоновку, вам придётся переписать её по новой.

Однако, встречаются ситуации, где допустимо использование абсолютного позиционирования. Например, мои учебные примеры. Я не хотел делать их слишком сложными, поэтому я часто использовал абсолютное позиционирование. Однако, в большинстве реальных программ программисты пользуются классификаторами.

В нашем примере мы реализуем простой набросок текстового редактора. Если мы изменим размеры окна, то размеры текстового поля вопреки нашим ожиданиям останутся неизменными.

Это пример использования абсолютного позиционирования. Мы расположили виджет wxTextCtrl (текстовое поле) на виджете панели.

textctrl = new wxTextCtrl(panel, -1, wxT(""), wxPoint(-1, -1),

wxSize(250, 150));

Мы используем абсолютное позиционирование в конструкторе виджета wxTextCtrl. В нашем случае мы задали основную позицию виджета по-умолчанию, ширину 250 пикселей и высоту 150 пикселей.

Использование классификаторов.

Классификаторы в wxWidgets позволяют получить те же результаты, что и абсолютное позиционирование. Мы можем выбирать между следующими классификаторами:

* wxBoxSizer (Прямоугольный классификатор)

* wxStaticBoxSizer (Статический прямоугольный классификатор)

* wxGridSizer (Табличный классификатор)

* wxFlexGridSizer (Гибкий табличный классификатор)

* wxGridBagSizer

Теперь вы можете сказать, что не видели никаких классификаторов в примере. На самом деле в этом примере содержится небольшая хитрость. Фактически мы поместили виджет wxTextCtrl внутри виджета wxFrame . Этот виджет (wxFrame) имеет специальный встроенный классификатор. Мы можем добавить только один виджет в контейнер wxFrame. Потомок виджета занимает всё свободное пространство кроме рамки окна, меню, панели инструментов, и строки состояния.

wxBoxSizer

Этот классификатор позволяет нам поместить несколько виджетов в строку или колонку. Мы можем поместить другой классификатор в уже существующий. Таким образом мы можем создавать очень сложные интерфейсы (компоновки).

wxBoxSizer(int orient)

wxSizerItem* Add(wxWindow* window, int proportion = 0, int flag = 0, int border = 0)

Ориентация может быть вертикальной (wxVERTICAL) или горизонтальной wxHORIZONTAL. Добавление виджетов в wxBoxSizer осуществляется методом Add(). Для лучшего понимания рассмотрим его параметры.

Параметр proportion определяет коэффициент того как виджеты будут изменяться в заданной ориентации. Предположим у нас есть три кнопки, значение параметра proportion 0, 1 и 2 соответственно. Они добавлены в горизонтальный классификатор wxBoxSizer. Кнопка с proportion = 0 не будет изменяться вообще. Кнопка с proportion = 2 будет изменяться в два раза сильнее кнопки с proportion = 1 в горизонтальном направлении.

С помощью параметра flag вы можете точнее настроить поведение виджетов внутри wxBoxSizer. Параметр border позволяет задать пространство между виджетами в пикселях. Для работы параметра border нужно с помощью параметра flag определить стороны, где нужно его использовать. Мы можем объединить их оператором |. Например wxLEFT | wxBOTTOM. Мы можем использовать следующие значения для параметра flag:

* wxLEFT

* wxRIGHT

* wxBOTTOM

* wxTOP

* wxALL

В этом примере мы создали две панели. Вторая панель окружена пустым пространством.

vbox->Add(midPan, 1, wxEXPAND | wxALL, 20);

Мы поместили границу шириной 20 пикселей вокруг панели midPan. wxALL применяет размер гарницы для четырёх сторон. Если мы используем wxEXPAND флаг, виджет будет использовать всё пространство, выделенное для него.

В заключении мы определили выравнивание наших виджетов. Мы сделали это используя следующие флаги:

* wxALIGN_LEFT

* wxALIGN_RIGHT

* wxALIGN_TOP

* wxALIGN_BOTTOM

* wxALIGN_CENTER_VERTICAL

* wxALIGN_CENTER_HORIZONTAL

* wxALIGN_CENTER

Допустим, мы захотим добавить две кнопки в правой нижней части окна.

Мы создали три классификатора. Один вертикальный и два горизонтальных. Мы поместили два горизонтальный классификатора в вертикальный.

hbox1->Add(new wxPanel(panel, -1));

vbox->Add(hbox1, 1, wxEXPAND);

Мы поместили wxPanel в первый горизонтальный классификатор. Установили параметр proportion равным 1 и флаг wxEXPAND. В этом случае классификатор заполнит всё пространство кроме hbox2.

vbox->Add(hbox2, 0, wxALIGN_RIGHT | wxRIGHT | wxBOTTOM, 10);

Мы поместили кнопки в классификатор hbox2, т.к. он находится по правую сторону окна, поэтому мы так же добавляем немного места сверху и справа от кнопок.

Go To Class

Следующий пример иллюстрирует несколько важных идей.

Это сложный пример использования классификатора wxBoxSizer. Расположение строго сверху. Мы создали один вертикальный классификатор и поместили в него пять горизонтальных.

vbox->Add(hbox3, 1, wxLEFT | wxRIGHT | wxEXPAND, 10);

vbox->Add(-1, 25);

Мы знаем, что можем контролировать расстояние межу виджетами, комбинируя значения параметров flag и border. Но тут существует одно серьёзное ограничение. В методе Add() мы можем указать только одну границу (border) для всех заданных сторон. В нашем примере мы задали 10 пикселей справа и слева, но мы не можем тут же задать 25 пикселей снизу. Все что мы можем сделать так это добавить сверху так же 10 пикселей или вообще их не добавлять (если опустим флаг wxBOTTOM). Поэтому если нам нужна другая величина, то мы можем добавить немного дополнительного пространства. Ведь с помощью метода Add() мы можем добавлять как виджеты, так и пространство.

vbox->Add(hbox5, 0, wxALIGN_RIGHT | wxRIGHT, 10);

Мы поместили две кнопки с правой стороны окна. Как мы это сделали? Три вещи необходимы, чтобы этого добиться. Параметр proportion, флаг wxALIGN_RIGHT и флаг wxEXPAND. Proportion должен быть равен 0. Кнопки не должны изменять своего размера, когда мы растягиваем окно. Мы не должны указывать флаг wxEXPAND. Кнопки должны занимать только то место, которое для них выделено. И в завершении нужно указать флаг wxALIGN_RIGHT. Горизонтальный классификатор растягивается на всю ширину окна. Поэтому если мы укажем флаг wxALIGN_RIGHT, то кнопки будут помещены справа, как раз так как мы и хотели.

wxGridSizer

Этот классификатор располагает виджеты в двумерной таблице. Ячейки внутри таблицы имеют одинаковый размер.

wxGridSizer(int rows, int cols, int vgap, int hgap)

В конструкторе мы указываем количество строк и столбцов таблицы. А так же пространство между ячейками по вертикали и горизонтали.

В нашем примере мы создадим скелет калькулятора. Это прекрасный образец использования wxGridSizer.

В этом примере мы использовали вертикальный классификатор для wxFrame. Так же мы поместили статический текст и табличный классификатор в вертикальный классификатор.

Кстати, обратите внимание на то, как мы добавили пространство между клавишами Bck и Close. Мы просто вставили между ними пустой wxStaticText. Такие трюки очень распространены.

gs->Add(new wxButton(this, -1, wxT("Cls")), 0, wxEXPAND);

Метод Add() вызывается много раз. Виджеты располагаются внутри таблицы в порядке добавления. Первый ряд заполняется первым, второй - вторым и т.д.

wxFlexGridSizer

Этот классификатор похож на wxGridSizer, он так же размещает виджеты внутри двумерной таблицы. Но он делает это размещение более гибким. В wxGridSizer все ячейки одного размера. В wxFlexGridSizer ячейки имеют одинаковую высоту внутри строки и одинаковую ширину внутри столбца. Но в разных строках и столбцах высота и ширина могут различаться.

wxFlexGridSizer(int rows, int cols, int vgap, int hgap)

Параметры rows и cols задают количество строк и столбцов в классификаторе. vgap и hgap определяют пространство между виджетами в обоих направлениях.

Много времени разработчики тратят на разработку диалогов для ввода и изменения данных. Я нахожу wxFlexGridSizer очень удобным для реализации подобных вещей. Программист может без труда создать диалоговое окно с помощью этого классификатора. Правда, можно сделать то же самое и с помощью wxGridSizer, но выглядеть это будет не так хорошо, из-за того, что все ячейки имеют одинаковый размер.

В нашем примере мы создали простой диалог. Он может быть использован для ввода данных в базу данных.

wxBoxSizer *hbox = new wxBoxSizer(wxHORIZONTAL);

...

hbox->Add(fgs, 1, wxALL | wxEXPAND, 15);

Мы создали горизонтальный классификатор с целью добавить немного пространства (15 пикс) вокруг таблицы виджетов.

fgs->Add(thetitle);

Мы добавили виджеты в классификатор точно так же как и в GridSizer.

fgs->AddGrowableRow(2, 1);

fgs->AddGrowableCol(1, 1);

Мы создали третью строку и второй столбец масштабируемыми. Точно так мы создали масшабируемые текстовые элементы управления, которые изменяются в размерах при изменении размеров окна. Первые два текстовых элемента управления увеличиваются в горизонтальном направлении, а третий в обоих. Так же помните, что нужно сделать виджеты растяжимыми (wxEXPAND) для того, чтобы всё заработало.

Original (English): The wxWidgets programming tutorial (4. Layout management in wxWidgets)

Translation: © ber113 .

translated.by crowd

Like this translation? Share it or bookmark!