Визуализация виджетов

Создание виджетов само по себе не делает виджет видимым. Виджет становится видимым когда выполняются следующие условия:

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

Взятие виджетов на управление

Родительские виджеты являются ответственными за геометрию своих потомков. Потомок может спросить своего родителя принять данные размеры и позицию, а родитель примет решение разрешить или нет этот запрос. Родитель может переместить или изменить размер дочернего окна без разрешения потомка. Поцесс посредством которого родитель и потомок взаимодействуют с целью определения геометрии виджета описывается в главе 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 для реализации виджета. Эта подпрограмма делает следующее:

Имейте в виду следующие:

Когда дерево виджетов делается видимым первый раз приложение должно обычно взять на управление все виджеты, а затем реализовать только виджет верхнего уровня. Это приводит к тому, что все начальные размеры и положения потомков и общий размер окна верхнего уровня будет определены пока не существует никаких окон, что уменьшит взаимодействие с 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 для создания различных виджетов верхнего уровня для каждого логического приложения.