> **Источник:** https://python-all.ru/2.7/library/framework.html
>
> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.

---

# 37.6. [`FrameWork`](https://python-all.ru/2.7/library/framework.html#module-FrameWork) – Интерактивный каркас приложений

Модуль [`FrameWork`](https://python-all.ru/2.7/library/framework.html#module-FrameWork) содержит классы, которые вместе образуют каркас для создания интерактивных приложений Macintosh. Программист строит приложение, создавая подклассы и переопределяя различные методы базовых классов, реализуя таким образом нужную функциональность. Переопределение функциональности часто можно выполнять на разных уровнях: например, чтобы обрабатывать щелчки в отдельном диалоговом окне нестандартным способом, не нужно переопределять всю обработку событий.

> **Примечание**
>
> Этот модуль был удалён в Python 3.x.

Работа над [`FrameWork`](https://python-all.ru/2.7/library/framework.html#module-FrameWork) практически прекращена, теперь, когда `PyObjC` доступен для полного доступа к Cocoa из Python, а документация описывает только самую важную функциональность, и притом не самым логичным образом. Для получения более подробной информации изучите исходный код или примеры. Ниже приведены некоторые комментарии, опубликованные в новостной группе MacPython, о сильных и слабых сторонах [`FrameWork`](https://python-all.ru/2.7/library/framework.html#module-FrameWork):

> Сильная сторона [`FrameWork`](https://python-all.ru/2.7/library/framework.html#module-FrameWork) в том, что он позволяет вмешиваться в поток управления во многих точках. [`W`](https://python-all.ru/2.7/library/undoc.html#module-W), например, использует другой способ включения/отключения меню, и это легко встраивается, оставляя остальное нетронутым. Слабые стороны [`FrameWork`](https://python-all.ru/2.7/library/framework.html#module-FrameWork): отсутствие абстрактного интерфейса команд (но это не должно быть сложно исправить), минимальная поддержка диалогов и полное отсутствие поддержки элементов управления и панелей инструментов.

Модуль [`FrameWork`](https://python-all.ru/2.7/library/framework.html#module-FrameWork) определяет следующие функции:

#### `FrameWork.Application()`

Объект, представляющий приложение целиком. Описание методов см. ниже. Стандартная процедура [`__init__()`](https://python-all.ru/2.7/reference/datamodel.html#object.__init__) создает пустой словарь окон и строку меню с меню Apple.

#### `FrameWork.MenuBar()`

Объект, представляющий строку меню. Обычно этот объект не создается пользователем.

#### `FrameWork.Menu(bar, title[, after])`

Объект, представляющий меню. При создании вы передаете `MenuBar`, в котором будет меню, строку *заголовок* и позицию (начиная с 1) *после*, где должно появиться меню (по умолчанию – в конце).

#### `FrameWork.MenuItem(menu, title[, shortcut, callback])`

Создает объект пункта меню. Аргументы: меню, в котором создается пункт, строка заголовка пункта, а также, опционально, сочетание клавиш и функция обратного вызова (колбэк). Колбэк вызывается с аргументами: идентификатор меню, номер пункта внутри меню (начиная с 1), текущее переднее окно и запись события.

Вместо вызываемого объекта в качестве колбэка можно передать строку. В этом случае при выборе пункта меню выполняется поиск метода в верхнем окне и приложении. Имя метода образуется путем добавления `'domenu_'` к строке колбэка.

Вызов метода `MenuBar` `fixmenudimstate()` устанавливает правильное отключение для всех пунктов меню в зависимости от текущего переднего окна.

#### `FrameWork.Separator(menu)`

Добавляет разделитель в конец меню.

#### `FrameWork.SubMenu(menu, label)`

Создает подменю с именем *label* в меню *menu*. Возвращается объект меню.

#### `FrameWork.Window(parent)`

Создает (немодальное) окно. *Parent* – это объект приложения, которому принадлежит окно. Окно не отображается до следующего вызова.

#### `FrameWork.DialogWindow(parent)`

Создает немодальное диалоговое окно.

#### `FrameWork.windowbounds(width, height)`

Возвращает кортеж `(left, top, right, bottom)`, подходящий для создания окна заданной ширины и высоты. Окно будет смещено относительно предыдущих окон, и предпринимается попытка уместить всё окно на экране. Однако окно всегда будет точно заданного размера, поэтому его части могут оказаться за пределами экрана.

#### `FrameWork.setwatchcursor()`

Устанавливает курсор мыши в режим песочных часов (watch).

#### `FrameWork.setarrowcursor()`

Устанавливает курсор мыши в виде стрелки.

## 37.6.1. Объекты приложения

Объекты приложения имеют следующие методы, в числе прочих:

#### `Application.makeusermenus()`

Переопределите этот метод, если вашему приложению нужны меню. Добавьте меню в атрибут `menubar`.

#### `Application.getabouttext()`

Переопределите этот метод, чтобы вернуть текстовую строку с описанием приложения. В качестве альтернативы можно переопределить метод `do_about()` для более подробных сообщений «О программе».

#### `Application.mainloop([mask[, wait]])`

Эта процедура является основным циклом событий; вызовите её, чтобы запустить приложение. *Mask* – это маска событий, которые нужно обрабатывать; *wait* – количество тиков (ticks), которое следует выделить другим параллельным приложениям (по умолчанию 0, что, вероятно, не очень хорошая идея). Хотя вызов *self* для выхода из основного цикла по-прежнему поддерживается, это не рекомендуется: вместо этого вызывайте `self._quit()`.

Цикл событий разбит на множество небольших частей, каждую из которых можно переопределить. Методы по умолчанию занимаются диспетчеризацией событий окнам и диалогам, обработкой перетаскивания и изменения размеров, событий Apple, событий для окон, не относящихся к FrameWork, и т.д.

В общем случае все обработчики событий должны возвращать `1`, если событие полностью обработано, и `0` в противном случае (например, потому что переднее окно не было окном FrameWork). Это нужно, чтобы события обновления и подобные могли передаваться другим окнам, например окну консоли Sioux. Вызов `MacOS.HandleEvent()` не разрешен внутри *our\_dispatch* или вызываемых им функций, так как это может привести к бесконечному циклу, если код вызывается через обработчик событий внутреннего цикла Python.

#### `Application.asyncevents(onoff)`

Вызовите этот метод с ненулевым параметром, чтобы включить асинхронную обработку событий. Это укажет внутреннему циклу интерпретатора вызывать обработчик событий приложения *async\_dispatch* всякий раз, когда доступны события. Это позволит обновлениям окон FrameWork и пользовательскому интерфейсу оставаться рабочими во время длительных вычислений, но замедлит работу интерпретатора и может привести к неожиданным результатам в нереентерабельном коде (например, в самом FrameWork). По умолчанию *async\_dispatch* немедленно вызывает *our\_dispatch*, но вы можете переопределить это поведение, чтобы обрабатывать асинхронно только определённые события. События, которые вы не обрабатываете, будут переданы Sioux и подобным.

Возвращается предыдущее значение вкл/выкл.

#### `Application._quit()`

Завершить выполняющийся вызов [`mainloop()`](https://python-all.ru/2.7/library/framework.html#FrameWork.Application.mainloop) при ближайшей удобной возможности.

#### `Application.do_char(c, event)`

Пользователь ввёл символ *c*. Полные подробности события можно найти в структуре *event*. Этот метод также может быть предоставлен в объекте `Window`, который переопределяет общеприкладной обработчик, если окно является передним.

#### `Application.do_dialogevent(event)`

Вызывается в начале цикла событий для обработки событий немодальных диалогов. Метод по умолчанию просто отправляет событие соответствующему диалогу (не через задействованный объект `DialogWindow`). Переопределите, если требуется специальная обработка событий диалога (клавиатурные сокращения и т.д.).

#### `Application.idle(event)`

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

## 37.6.2. Объекты окна

Объекты Window имеют следующие методы, среди прочих:

#### `Window.open()`

Переопределите этот метод, чтобы открыть окно. Сохраните идентификатор окна Mac OS в `self.wid` и вызовите метод `do_postopen()` для регистрации окна в родительском приложении.

#### `Window.close()`

Переопределите этот метод для выполнения специальной обработки при закрытии окна. Вызовите метод `do_postclose()`, чтобы очистить состояние родителя.

#### `Window.do_postresize(width, height, macoswindowid)`

Вызывается после изменения размера окна. Переопределите, если требуется сделать больше, чем просто вызов `InvalRect`.

#### `Window.do_contentclick(local, modifiers, event)`

Пользователь щёлкнул в области содержимого окна. Аргументы: координаты (относительно окна), модификаторы клавиш и исходное событие.

#### `Window.do_update(macoswindowid, event)`

Получено событие обновления окна. Перерисуйте окно.

#### `Window.do_activate(activate, event)`

Окно было активировано (`activate == 1`) или деактивировано (`activate == 0`). Обработайте такие вещи, как подсветка фокуса и т.д.

## 37.6.3. Объект ControlsWindow

Объекты ControlsWindow имеют следующие методы помимо методов объектов `Window`:

#### `ControlsWindow.do_controlhit(window, control, pcode, event)`

Часть *pcode* элемента управления *control* была нажата пользователем. Отслеживание и прочее уже обработано.

## 37.6.4. Объект ScrolledWindow

Объекты ScrolledWindow являются объектами ControlsWindow со следующими дополнительными методами:

#### `ScrolledWindow.scrollbars([wantx[, wanty]])`

Создайте (или уничтожьте) горизонтальные и вертикальные полосы прокрутки. Аргументы указывают, какие из них нужны (по умолчанию обе). Полосы прокрутки всегда имеют минимум `0` и максимум `32767`.

#### `ScrolledWindow.getscrollbarvalues()`

Вы должны предоставить этот метод. Он должен возвращать кортеж `(x, y)`, указывающий текущее положение полос прокрутки (между `0` и `32767`). Вы можете вернуть `None` для любой из них, чтобы указать, что весь документ виден в этом направлении.

#### `ScrolledWindow.updatescrollbars()`

Вызовите этот метод, когда документ изменился. Он вызовет [`getscrollbarvalues()`](https://python-all.ru/2.7/library/framework.html#FrameWork.ScrolledWindow.getscrollbarvalues) и обновит полосы прокрутки.

#### `ScrolledWindow.scrollbar_callback(which, what, value)`

Предоставляется и вызывается после взаимодействия с пользователем. *which* будет `'x'` или `'y'`, *what* будет `'-'`, `'--'`, `'set'`, `'++'` или `'+'`. Для `'set'`, *value* будет содержать новое положение полосы прокрутки.

#### `ScrolledWindow.scalebarvalues(absmin, absmax, curmin, curmax)`

Вспомогательный метод, помогающий вычислить значения для возврата из [`getscrollbarvalues()`](https://python-all.ru/2.7/library/framework.html#FrameWork.ScrolledWindow.getscrollbarvalues). Передаётся минимальное и максимальное значение документа, а также верхнее (левое) и нижнее (правое) видимые значения, и возвращается правильное число или `None`.

#### `ScrolledWindow.do_activate(onoff, event)`

Занимается затемнением/подсветкой полос прокрутки, когда окно становится передним. Если этот метод переопределяется, его следует вызывать в конце переопределяющего метода.

#### `ScrolledWindow.do_postresize(width, height, window)`

Перемещает полосы прокрутки в правильное положение. Этот метод следует вызывать в начале, если он переопределяется.

#### `ScrolledWindow.do_controlhit(window, control, pcode, event)`

Обрабатывает взаимодействие с полосами прокрутки. Если этот метод переопределяется, его следует вызывать первым; ненулевое возвращаемое значение указывает, что попадание пришлось на полосы прокрутки и было обработано.

## 37.6.5. Объекты DialogWindow

Объекты DialogWindow имеют следующие методы в дополнение к методам объектов `Window`:

#### `DialogWindow.open(resid)`

Создаёт диалоговое окно из ресурса DLOG с идентификатором *resid*. Объект диалога сохраняется в `self.wid`.

#### `DialogWindow.do_itemhit(item, event)`

Был активирован элемент номер *item*. Ответственность за перерисовку переключателей и т.п. лежит на вызывающем коде.
