Создание виджетов само по себе не делает виджет видимым. Виджет становится видимым когда выполняются следующие условия:
Виджет и его родители взяты на управление. Виджет взят на управление когда менеджеры геометрии Xt и Motif получают формуляр виджета при проведении расчета положения и размера виджетов на дисплее.
Виджет и его родители реализованы. Виджет считается релизованным когда он имеет связанное с ним окно.
Виджет и его родители отображены. Виджет является отображенными когда его окно отображено на экране.
Приложение может брать на управление, реализовывать и отображать виджеты отдельными шагами, но каждое из этих действий влияет на другие.
Родительские виджеты являются ответственными за геометрию своих потомков. Потомок может спросить своего родителя принять данные размеры и позицию, а родитель примет решение разрешить или нет этот запрос. Родитель может переместить или изменить размер дочернего окна без разрешения потомка. Поцесс посредством которого родитель и потомок взаимодействуют с целью определения геометрии виджета описывается в главе 14.
Приложение указывает виджету взять на управление геометрию дочерних виджетов посредством вызова XtManageChild или XtManageChildren. Если родительский виджет реализован, то XtManageChild вызывает процедуру change_managed родительского виджета. Эта процедура может изменить размер или положение любого потомка родительского виджета. После вызова процедуры change_managed родительского виджета XtManageChild проводит реализацию потомка и, если ресурс \textbl{XmNmappedWhenManaged} потомка установлен в True, то и отображает его.
Если родительский виджет не реализован, то XtManageChild отмечает, что потомок взят на управление. Xt откладывает вызов процедуры change_managed родительского виджета пока родительский виджет не будет реализован.
Когда берется на управление более одного потомка реализованного родительского виджета приложению более выгодно вызвать XtManageChildren вместо отдельного вызова XtManageChild для каждого отдаваемого на управление виджета. Расположение виджетов может потребовать значительных расчетов, а XtManageChild вызывает процедуру change_managed каждый раз когда вызывается. XtManageChildren вызывает процедуру change_managed только один раз для всех потомков взятых на управление.
Приложение указывает виджету не производить управление геометрией дочерних виджетов посредством вызова XtUnmanageChild или XtUnmanageChildren. С помощью взятия на управление и снятия с управления виджетов приложение может альтернативно отображать более одного набора потомков без применения процедур создания и уничтожения виджетов каждый раз когда изменяется конфигурация приложения. Дополнительно, взятие на управление диалогов и всплывающих меню заставляет виджет появиться на экране, а снятие с управление заставляет исчезнуть с экрана.
Для создания виджета и взятия его на управление в одном вызове приложение может использовать XtCreateManagedWidget или XtVaCreateManagedWidget. Подпрограммы Motif создающие виджеты определенного класса всегда возвращают не взятые на управление виджеты. Когда используются эти подпрограммы приложение должно самостоятельно отдать на управление виджеты используя XtManageChild или XtManageChildren.
Приложение использует XtRealizeWidget для реализации виджета. Эта подпрограмма делает следующее:
В пост-порядке обходит дерево виджетов, чиьм корнем является виджет и вызывает процедуру change_managed класса для каждого виджета в дереве имеющего взятые на управление потомки.
Рекурсивно обходит дерево корнем является виджет и вызывает процедуру realize класса для каждого виджета в дереве который взят на управление. Процедура realize создает окна виджетов.
Отображает вятые на управление потомки виджета у которых \textbl{XmNmappedWhenManaged} установлен в True. Если виджет является виджетом верхнего уровня и ресурс \textbl{XmNmappedWhenManaged} установлен в True, то XtRealizeWidget отображает его.
Имейте в виду следующие:
Согласование геометрии производится снизу вверх, тогда как создание окон производится сверху вниз.
После того, как виджет реализован все его взятые на управление потомки реализованы и, по умолчанию, отображены.
Если в дереве нет реализованных виджетов, то все согласование геометрии между родителями и их взятыми на управление потомками будет проведено перед реализацией любого виджета.
Когда дерево виджетов делается видимым первый раз приложение должно обычно взять на управление все виджеты, а затем реализовать только виджет верхнего уровня. Это приводит к тому, что все начальные размеры и положения потомков и общий размер окна верхнего уровня будет определены пока не существует никаких окон, что уменьшит взаимодействие с X сервером. Это также позволяет приложению реализовать все виджеты одним вызовом XtRealizeWidget.
Большинство приложение не производят непосредственного отображения и снятия с отображения окон виджетов. Отображение обычно имеет место как часть процесс взятия на управление или реализации виджетов. Но имеется возможность предохранить Xt от отображения окон в это время установкой ресурса \textbl{XmNmannedWhenManaged} в False. В этом случае приложение должно непосредственно использовать XtMapWidget для отображения виджета. Приложение может использовать XtUnmapWidget для отмены отображения виджета.
Эффект от взятия виджета на управление с отмененным отображением отличен от снятия виджета с управления. Когда виджет снят с управления его родитель не получает его формуляр при расположении своих потомков. Когда виджет взят на управнение его родитель сохраняет место для расположения виджета. Когда родитель отображен место, выделенное для управляемого, но неотображенного потомка заполняется фоном родительского окна, а не фоном окна потомка.
Приложение может быть запущено более чем на одном экране. В этом случае оно должно использовать XOpenDisplay для установления соединения с каждым дисплем и должно затем выполнить XtDisplayInitlaize отдельно для каждого соединения. Ему необходимо создать собственный контекст приложения для каждого дисплея.
XtDisplayInitialize изменяет аргументы argv и argv. Если приложению необходимо вызвать XtDisplayInitialize более чем один раз оно должно сохранить эти аргументы перед первым вызовом и использовать копию сохраненных аргументов для каждого вызова. |
Приложение должно использовать XtAppCreateShell для создания хотябы одного виджета верхнего уровня на каждом дисплее на котором производится запуск. Поскольку Xt поддерживает раздельные базы данных ресурсов для каждого дисплея, то дочерний виджет, запущенный на дисплее, отличном от того на котором запущен родительский виджет, будет использовать некорректные начальные значения ресурсов.
Приложение также может быть запущено более чем на одном экране дисплея. Т.к. приложение открывает и инициализирует дисплей только единожды, то не имеет значения насколько много экранов оно использует на дисплее. Тем не менее, приложению также необходим виджет на каждом экране, чье окно является потомком корневого окна этого экрана для использования виджета как корня иерархии виджетов на этом экране.
Одним из подходов к использованию нескольких экранов является создание единственной нереализованной оболочки ApplicationShell для дисплея. Приложение затем создает одну оболочку TopLevelShell для каждого экрана как всплывающего потомка от ApplicationShell. Поскольку оболочка способна нормально содержать только один управляемый виджет, она может иметь более чем одного всплывающего потомка. Приложение использует XtAppCreateShell для создания оболочки ApplicationShell и XtCreatePopupShell для создания каждой оболочки TopLevelShell. Если не указывать экран для ApplicationShell, то XtAppCreateShell установит в ресурсе \textbl{XmNscreen} этого виджета экран по умолчанию на дисплее. В списке параметров передаваемом в XtCreatPopupShell приложение должно указать соответствующее значение для ресурса \textbl{XmNscreen} для каждой оболочки TopLevelShell чтобы эта оболочка создается на необходимом экране.
Приложение не должно брать на управление оболочки TopLevelShell. Для реализации и отображения этих оболочек приложение должно использовать XtPopup с аргументом grab_kind установленным в \textbl{XtGrabNone}.
int main(int argc, char **argv) { Widget app_shell, top_shell; XtAppContext app; Display *display; char name[20]; Arg args[5]; Cardinal n; int i; app_shell = XtAppInitialize(&app, "Example", (XrmOptionDescList) NULL, 0, &argc, argv, (String *) NULL, (ARGList) NULL, 0); display = XtDisplay(app_shell); for (I = 0; i < ScreenCount(display); i++) { sprintf(name, "top_shell_%d", i); n = 0; XtSetArg(args[n], XmNscreen, ScreenOfDisplay(display, i)); n++; top_shell = XtCreatePopupShell(name, topLevelShellWidgetClass, app_shell, args, n); /* создание и взятие на управление потомков оболочки */ ... /* реализация и отображение оболочки */ XtPopup(top_shell, XtGrabNone); } ... } |
Пограмма может иметь несколько логических приложений на одном экране. В этом случае она использует XtAppCreateShell для создания различных виджетов верхнего уровня для каждого логического приложения.