Общие сведения о Tk. Лабораторная работа №3


Лабораторная работа №3 «Общие сведения о Tk»

Tk – это набор инструментальных средств, предназначенных для про­граммирования графических пользовательских интерфейсов. Он был разра­ботан для системы X Window, используемой в среде Unix, а впоследствии был перенесен на платформы Macintosh и Windows. В Тк действуют мно­гие из понятий, лежащих в основе других оконных систем, однако, для того чтобы решать простые задачи с помощью Тк, не обязательно обладать спе­циальными знаниями о графических пользовательских интерфейсах.

Тк предоставляет разработчику набор Tcl-команд, предназначенных для создания компонентов и выполнения различных действий с ними. Компо­нент представляет собой окно в составе графического интерфейса, имеющее определенный внешний вид и выполняющее некоторые функции. В принципе термины компонент и окно настолько близки, что они могут использоваться один вместо другого. Компоненты бывают различных типов. Чаще других ис­пользуются кнопки, полосы прокрутки, меню и текстовые окна. В Тк также реализован компонент общего назначения под названием холст (canvas), ко­торый позволяет выводить простые рисунки и растровые изображения. Воз­можности холста достаточно велики, при этом работать с ним очень просто.

Компоненты организованы в иерархическую структуру. С точки зрения приложения существует главное, или первичное, окно, в котором создаются дочерние окна. Дочерние окна, в свою очередь, могут выступать в качестве родительских по отношению к другим окнам и т.д. Подобно тому, как в иерар­хической файловой системе каталоги выступают в качестве контейнеров для файлов и других каталогов, так и в оконной системе некоторые окна играют роль контейнеров для других окон. Иерархия окон влияет на принцип име­нования компонентов Тк и позволяет упорядочивать окна на экране.

Компонентами управляют диспетчеры компоновки (geometry manager), которые определяют размеры компонентов и их размещение на экране. До тех пор пока диспетчер компоновки не получит сведения о компоненте, для по­следнего не будет выделено пространство на экране и пользователь не увидит его. В Тк содержатся мощные диспетчеры компоновки, которые существенно упрощают размещение компонентов на экране. В основу работы любого дис­петчера компоновки положен тот факт, что одни компоненты, называемые фреймами, выступают в роли контейнеров для других компонентов. Поме­щая фреймы в другие фреймы, можно реализовать сложные экранные фор­мы. В Тк реализованы три диспетчера компоновки: grid, pack и place. Кро­ме того, компонент panedwindow также может рассматриваться как диспетчер компоновки.

Tk-приложения, как и большинство оконных приложений, представляют собой программы, управляемые событиями. Компоненты Тк автоматически обрабатывают большинство событий, что упрощает задачу разработчиков по созданию приложений. Чтобы реализовать более сложное поведение интер­фейса, надо связать с помощью команды bind с событием одну или несколько Tcl-команд. При работе Tk-приложения могут возникать самые различные события, например, перемещение мыши, изменение размеров окна, нажатие клавиши на клавиатуре, удаление окна и т.д. Кроме того, вы можете опреде­лять виртуальные события, например Cut или Paste; на разных платформах им будут соответствовать различные события.

Связи между событиями и командами объединяются в классы, называ­емые дескрипторами связей (bindtag). Команда bindtags связывает компо­зит с упорядоченным наборов дескрипторов связей. Возможность исполь­зования косвенных связей между обработчиками события и компонентами, генерирующими их, позволяют создавать гибкие и мощные системы. По необходимости вы можете создавать свои дескрипторы связей и динамически из­менять их, влияя тем самым на поведение приложения.

Понятие фокуса имеет непосредственное отношение к связыванию собы­тий с обработчиками. В каждый момент времени тот или иной компонент имеет фокус ввода, и события клавиатуры направляются этому компоненту. Существуют два основных способа назначения фокуса: передача его компо­ненту, на котором расположен курсор мыши, и явная передача фокуса кон­кретному компоненту. Тк предоставляет команды для обработки фокуса вво­да, поэтому вы можете реализовать любой из способов управления фокусом. Для реализации модальных диалоговых окон приходится перехватывать фо­кус.

Как правило, выполнение Tk-сценария начинается с создания компонен­тов и размещения их с помощью диспетчера компоновки, после чего сценарий связывает обработчики событий с компонентами. После того как интерпре­татор оканчивает разбор команд, ответственных за инициализацию пользо­вательского интерфейса, он переходит в цикл обработки событий. С этого момента приложение начинает реагировать на действия пользователя. Про­грамму wish можно запустить для интерактивной работы. В этом режиме она создает и отображает пустое главное окно, а также выводит подсказ­ку для ввода команды. Команды, вводимые с клавиатуры, обрабатываются в цикле событий, что позволяет постепенно, шаг за шагом, формировать ин­терфейс Tk-приложения. Как вы вскоре убедитесь, Тк позволяет изменить в интерактивном режиме почти все характеристики приложения.

Первый рассматриваемый Тк-сценарий очень прост (пример 3.1). При его выпол­нении создается кнопка, после щелчка на которой в стандартный выходной поток записывается последовательность символов «Hello, World!». Над кноп­кой размещается строка заголовка, которую формирует оконный диспетчер. Поскольку данный пример запускался в среде X Window, в качестве оконного диспетчера использовался twm.

Пример 3.1.

button .hello -text Hello -command {puts stdout «Hello, World!»}

pack .hello —padx 20 —pady 10

Сценарий, код которого приведен в примере 3.1, содержит две Тс1-команды: одна из них формирует кнопку, в другая делает ее видимой на экране. Для создания экземпляра кнопки предназначена команда button.

button  .hello  —text Hello —command {puts stdout  «Hello,  World!»}

=>   .hello

Созданная кнопка имеет имя .hello. Последовательность символов Hello представляет надпись на кнопке. Кроме того, с кнопкой связывается следующая команда:

puts  stdout  «Hello,  World!»

Команда pack размещает кнопку на экране. При вызове этой команды указаны опции, управляющие заполнением, поэтому вокруг кнопки выделяется свободное пространство.

pack   .hello  —padx 20  —pady 10

Если вы введете эти две команды в командной строке программы wish, вы будете наблюдать следующее. После выполнения команды button на экран не будут выводиться никакие данные. После того как вы введете команду pack размеры главного окна изменятся так, чтобы вместить кнопку и пу­стое пространство вокруг нее.

Для создания и именования компонентов в Тк используется объектная система. С каждым классом компонентов (например, классом Button) связывается команда, предназначенная для создания экземпляра этого класса. После того как компонент создан, определяется новая Tcl-команда, которая обрабатывает конкретный экземпляр компонента. В примере 3.1 формиру­ется кнопка .hello, и мы получаем возможность выполнять действия с этой кнопкой, используя ее имя как Tcl-команду. Например, мы можем указать способ подсвечивания, имитирующий мигание кнопки.

.hello flash

Мы также можем непосредственно вызвать команду, связанную с кноп­кой.

.hello invoke

=> Hello,   World!

Tk действует с классами и экземплярами компонентов, но не является в полном смысле слова объектно-ориентированным. Так, например, невоз­можно создать подкласс класса компонента и использовать наследование. Вместо этого Tk предоставляет очень гибкие компоненты, которые можно на­страивать различными способами для получения требуемого эффекта. Кон­фигурационные данные могут содержаться в базе ресурсов и совместно ис­пользоваться разными компонентами. Одинаковое поведение различных ком­понентов достигается за счет применения дескрипторов связывания. Вместо создания иерархии классов в Tk используются наборы компонентов с одина­ковыми атрибутами и сходным поведением.

Именование компонентов Tk. Точка, находящаяся в начале имени кнопки .hello, обязательно должна присутствовать. В Tk принята система именования компонентов, отражаю­щая их расположение в иерархии. Корнем иерархии является главное окно приложения. Его имя состоит из одной точки. В начале имени компонента, до­чернего по отношению к главному окну, указывается точка (например, .foo). Компонент bar, дочерний по отношению к .foo, обозначается как .foo.bar и т.д. Такой подход можно сравнить с принципом именования элементов фай­ловой системы Unix, где корневой каталог обозначается символом /, а затем тот же символ используется для разделения частей имени файла. Анало­гичную роль в именах компонентов Tk выполняет точка. Подобно тому, как в файловой системе каталоги являются контейнерами для файлов и других каталогов, так и в иерархии окон Tk компоненты-фреймы выступают в роли контейнеров для компонентов и других фреймов.

Каждый элемент в составе пути к Tk-компоненту должен начинаться со строчной буквы или с цифры. Очевидно, что в именах конкретных компонен­тов не может присутствовать точка. Применение символов нижнего регистра позволяет избежать конфликтов с именами классов ресурсов, которые по со­глашению начинаются с прописной буквы. Имена ресурсов могут включать элементы пути к компонентам Тк, и использование регистров символов поз­воляет различать их..

Имена компонентов желательно хранить в переменных. Система именования компонентов Тк имеет существенный недостаток. Изменения интерфейса могут повлиять на позицию компонента в иерархии. В этом случае приходится изменять его имя. Смягчить негативные последствия возникновения подобной ситуации можно, используя для хранения важных компонентов переменные. Коман­да, с помощью которой создается компонент, возвращает его имя.

set b [button .hello —text «Hello» —command {puts «Hello!»}]

Для выполнения операций с кнопкой вы можете использовать выраже­ние $b.

$b  configure  -background green

Настройка компонентов Tk. Код, приведенный в примере 3.1, демонстрирует принцип использова­ния именованных параметров в Tk-командах. Атрибуты компонентов зада­ются с помощью опций и их значений. Имя опции представляет собой имя атрибута, которому предшествует символ -; за опцией следует значение ат­рибута. Даже в самых простых Tk-компонентах предусмотрено около десяти атрибутов, которые задаются описанным выше способом, а сложные компо­ненты насчитывают более 30 атрибутов. Однако при создании интерфейса с помощью Тк разработчик должен задавать лишь те атрибуты, значения которых, принимаемые по умолчанию, не устраивают его. Этим обусловлена предельная простота примера «Hello, World!».

Каждый экземпляр компонента поддерживает операцию configure (ее имя можно сокращать до config), которая позволяет определять текущие значения атрибутов и изменять их. При указании операции config задаются такие же пары опция-значение, как и при создании компонента. Например, для того чтобы изменить цвет кнопки на красный, надо выполнить приве­денную ниже команду. Сделать это можно после того, как кнопка создана и отображена на экране.

.hello config —background red

С помощью операции config вы можете переопределить любые атрибуты, даже атрибуты text и command, которые задаются при создании компонента. Приведенная ниже команда превращает кнопку Hello в кнопку Goodbye.

.hello config —text Goodbye! —command exit

Для компонентов Tk предусмотрена операция cget, позволяющая опре­делить текущее значение атрибута.

.hello cget —background

=> red

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

.hello config -background

=> -background background Background #ffe4c4 red

Возвращаемое значение содержит опцию командной строки, имя ресур­са, имя класса, значение по умолчанию и текущее значение. Если при вызове configure вы не укажете ни одной опции, то получите информацию обо всех атрибутах компонента.

Атрибуты компонентов Tk и база ресурсов. К атрибуту компонента можно обратиться тремя различными способами: с помощью опции командной строки, по имени ресурса и посредством класса ресурса. Формат опций командной строки был рассмотрен выше. Имя оп­ции формируется путем добавления дефиса (-) к имени атрибута (например, -offvalue). Имя ресурса для атрибута не содержит дефиса, и внутри име­ни каждое слово начинается с прописной буквы (например, off Value). Имя класса ресурсов начинается с прописной буквы, и каждое слово внутри имени также начинается с прописной буквы (например, Off Value).

В таблицах, приведенных в данной книге, для обозначения атрибутов компонентов используются имена ресурсов. Если вы собираетесь использовать для работы с атрибутами ком­понентов средства поддержки ресурсов, вам необходимо знать со­глашения об именовании. Опция командной строки формируется из имени ресурса путем преобразования символов в нижний регистр. Основное преимущество использования ресурсов для работы с ат­рибутами состоит в том, что вам не придется «засорять» код сцена­рия фрагментами, предназначенными для определения атрибутов. Ограничившись несколькими записями базы ресурсов, вы сможете задать атрибуты для всех компонентов. Кроме того, если атрибу­ты определяются с помощью ресурсов, пользователь может указать альтернативную спецификацию ресурса и переопределить значения, заданные в приложении. Чаще всего этой возможностью пользуются для переопределения цвета и начертаний шрифтов.

Многие атрибуты являются общими для большинства компонентов Тк. Они описаны в отдельном документе справочной системы options. Каждая страница начинается с раздела STANDARD OPTIONS, в котором указано, какие из стандартных атрибутов применимы к компоненту. В таблицах, приведен­ных в данной книге, всегда указывается полный набор атрибутов компонента.

Команды Тк. Приведенные ниже таблицы содержат список команд, реали­зованных в Тк.

Команды для создания компонентов. В таблице 3.1 описаны команды, посредством которых создаются компонен­ты. В Тк содержится 18 компонентов, однако четыре из них представляют собой разновидности кнопок и еще пять предназначены для отображения текста.

Таблица 3.1 – Команды, предназначенные для создания компонентов

  Команда

 

Описание

 

  button Создает  кнопку
  canvas Создает компонент холст (canvas), который поддержи­вает линии, прямоугольники, битовые карты, изображе­ния, дуги, текст, многоугольники и встроенные компо­ненты
  checkbutton Создает кнопку-переключатель, связанную с Tcl-переменной
  entry- Создает компонент, предназначенный для ввода и редак­тирования одной строки текста
  frame Создает компонент-контейнер, используемый совместно с диспетчером компоновки
  label Создает многострочную текстовую метку. С ее помощью отображается текст, предназначенный только для чтения
  labelframe Создает компонент, выполняющий функции контейне­ра и используемый совместно с диспетчером компонов­ки. Этот компонент имеет дополнительные атрибуты по сравнению с обычной меткой (Тк 8.4)
  listbox Создает текстовый компонент, ориентированный на ра­боту со строками, предоставляющий возможности про­крутки
  menu Создает меню
  menubutton Создает кнопку, управляющую отображением меню
  message Создает многострочное текстовое сообщение, предназна­ченное только для чтения
  panedwindow Создает контейнер, способный управлять другими ком­понентами (Тк 8.4)
radiobutton Создает набор переключателей опций (кнопок с зависи­мой фиксацией), связанных с одной переменной  
scale Создает линейный регулятор, с помощью которого мож­но изменять значение переменной  
scrollbar Создает полосу прокрутки, которая может быть связана с другим компонентом  
spinbox Создает инкрементный регулятор — составной компо­нент, который содержит поле редактирования и кнопки, предназначенные для изменения значений в поле (Тк 8.4)  
text Создает текстовый компонент общего назначения с воз­можностью редактирования  
toplevel Создает фрейм, который может выполнять функции но­вого окна верхнего уровня  

Команды для выполнения действий с компонентами. Команды, приведенные в таблице 3.2, предназначены для выполнения раз­личных действий с компонентами. Они также обеспечивают управление фо­кусом ввода и связывание обработчиков событий. Кроме того, некоторые ко­манды реализуют диспетчеры компоновки.

 

Таблица 3.2 — Команды для выполнения действий с компонентами

Команда

 

Описание
bell Воспроизводит звуковой сигнал на терминале
bind Связывает Tcl-команду с событием
bindtags Создает классы связывания и управляет наследованием связывания
clipboard Управляет буфером обмена
destroy Удаляет компонент
event Определяет и генерирует виртуальные события
focus Обеспечивает управление фокусом ввода
font Запрашивает или устанавливает атрибуты шрифта
grab Перехватывает фокус ввода, не позволяя другим компо­нентам получить его
grid Размещает компоненты в виде таблицы и накладывает ряд дополнительных ограничений на расположение компонен­тов
image Создает изображения и выполняет с ними различные дей­ствия
lower Перемещает окно вниз по стеку
option Создает базу данных ресурсов и формирует запросы к ней
pack Компонует содержимое компонента
place Размещает компоненты на экране с указанием позиций
raise Перемещает окно вверх по стеку
selection Выполняет действия над выделенными данными
send Передает Tcl-команду другому Тк-приложению
tk Запрашивает или устанавливает имя приложения
tkerror Обработчик ошибок
tkwait Ожидание события
update Обновляет отображаемые данные путем обработки цикла событий
winfо Запрашивает состояние окна
wm Поддерживает взаимодействие с диспетчером окон

 

Диспетчеры компоновки

Диспетчеры компоновки предназначены для управления размещением компонентов. С помощью диспетчера pack определяется набор правил, ко­торые задают порядок размещения элементов. Диспетчеры компоновки pack и grid представляют собой диспетчеры общего назначения, a place применяется для специальных целей. В приведенных примерах в основном ис­пользуется pack — первый из диспетчеров компоновки, реализованных для Тк. Диспетчер grid стал поддерживаться начиная с версии Тк 4.1.

Диспетчер компоновки рассматривает некоторый компонент как роди­тельский, в котором размещены дочерние, или ведомые, элементы. Родитель­ское окно почти всегда представляет собой фрейм, но в некоторых случаях в этой роли выступают компоненты других типов. В каждый момент времени компонент может управляться только одним диспетчером компоновки, одна­ко для различных компонентов можно применять разные диспетчеры. Если компонент не находится под управлением диспетчера, он не отображается на экране.

Не следует применять диспетчеры pack и grid к одному и тому же компоненту. Для каждого конкретного компонента следует выбрать диспетчер, который будет размещать его дочерние элементы (чаще всего в ка­честве такого диспетчера выбирается pack или grid. Попытка одно­временного использования обоих диспетчеров приведет к тому, что программа окажется в бесконечном цикле. Данное правило относит­ся только к непосредственным потомкам управляемого компонента.

Для следующего уровня дочерних компонентов можно использовать другой диспетчер. Например, вы можете принять решение обрабо­тать все дочерние элементы главного окна (.) с помощью диспетчера компоновки pack. Если один из дочерних элементов главного окна представляет собой фрейм, то для размещения элементов в нем вы с равным успехом можете выбрать как pack, так и grid.

Диспетчер компоновки pack.

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

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

Размещение относительно направления. В примере 3.1 создаются два фрейма, которые размеща­ются относительно выбранного направления в главном окне. Верхний фрейм,      .one, имеет меньшие размеры, чем размеры главного окна, поэтому цвет фо­на главного окна виден по бокам компонента. Дочерние элементы по очереди выравниваются относительно указанного направления, поэтому компонент .one располагается в верхней части окна. В команде pack можно указать одно из четырех направлений: top, right, bottom и left. Направление top принимается по умолчанию.

Пример 3.1

  • Для главного окна выбирается черный цвет фона
    .
    config —bg black
  • Создание двух фреймов и размещение их с помощью диспетчера компоновки

frame .one -width 40 -height 40 -bg white

frame .two -width 100 -height 50 -bg grey50

pack .one .two -side top

Размеры окон и команда pack propagate. В примере 3.1 размеры главного окна уменьшались до величи­ны, достаточной для размещения двух дочерних компонентов. В большинстве случаев такое поведение является наиболее приемлемым. Однако, если вам надо, чтобы окно не уменьшалось, следует вызвать команду pack. Приме­няя эту команду к родительскому окну, вы добьетесь того, что оно не будет согласовывать свои размеры с размерами дочерних элементов (пример 3.2).

Пример 3.2.

frame   .one  -width 40  -height 40  -bg white

frame   .two  -width 100  -height 50  -bg grey50

pack  propagate  . false pack   .one   .two  -side top

Горизонтальное и вертикальное размещение. Внутри фрейма компоненты могут размещаться по горизонтали или по вертикали. Если вы попытаетесь объединить горизонтальное и вертикальное размещение, одновременно задавая различные типы выравнивания (напри­мер, left и top), результаты могут оказаться неожиданными для вас. Гораз­до лучше объявлять несколько фреймов и указывать в них различные типы выравнивания. Предположим, например, что в рассмотренном выше примере нам надо разместить в верхнем фрейме горизонтальный ряд кнопок. Сделать это можно с помощью фрагмента кода, приведенного в примере 3.3.

Пример 3.3

frame   .one -bg white

frame   .two -width  100  -height  50  -bg grey50

# Создание ряда кнопок

foreach b {alpha beta gamma} {

 button  .one.$b -text $b

 pack  .one.$b -side left }

 pack   .one   .two  —side top

По необходимости вы можете реализовать более сложную компоновку эле­ментов. Для этого надо создать вложенные фреймы и задать в них разные типы выравнивания. В том фрейме, в котором компоненты должны распола­гаться горизонтально, надо задать опцию —side left или —side right. Если же вам надо организовать вертикальное размещение компонентов, это дости­гается с помощью опций —side top и —side bottom.

В примере 3.4 вместо кнопки .one.gamma в состав фрейма включен еще один фрейм, содержащий две кнопки: .one .right .delta и .one .right .epsilon. Эти кнопки расположены по вертикали. Поскольку при компоновке компонентов в .one.right указана опция —side bottom, первая включаемая кнопка размещается в нижней части фрейма.

Пример 3.4.

frame   .one -bg white

frame   .two -width 100 -height 50 -bg grey50

foreach b {alpha beta} {

button  .one.$b -text $b

pack  .one.$b -side left }

# Создание фрейма для двух дополнительных кнопок

 frame .one.right foreach b {delta epsilon} {

button .one.right.$b -text $b

pack .one.right.$b -side bottom }

pack  .one.right -side right pack   .one   .two -side top

В данном примере фрейм .one .right располагается в правой части роди­тельского фрейма, а в предыдущем случае при компоновке кнопки .one .gamma была указана опция —side left. Несмотря на различие опций, расположение этих компонентов относительно двух других кнопок, включенных во фрейм .one, остается неизменным. Причина этого будет объяснена далее.

Модель полостей. Алгоритм компоновки распределяет доступное пространство внутри фрейма в соответствии с моделью полостей. При создании окна wish главный фрейм пуст, и пространство для размещения компонентов не определено. Это пространство принято называть полостью (cav­ity). Согласно основному правилу компоновки, компонент заполня­ет полость по одной из координат. Рассмотрим пример 3.5 размещения трех компонентов в главном окне. Для первых двух компонентов зададим тип выравнивания bottom, а для третьего — тип выравни­вания right.

Пример 3.5.

# Размещение двух фреймов с выравниванием по нижней части,

frame   .one  -width  100  -height  50 -bg grey50

frame .two -width 40 -height 40 -bg white

pack .one .two —side bottom

# Размещение фрейма с выравниванием по правой части. —

frame .three -width 20 -height 20 -bg grey75

pack .three —side right

Если при размещении третьего фрейма в главном окне мы зададим опцию —side left или —side right, то расположим его в полости, находящейся над двумя фреймами, которые к этому моменту помещены в окно. Может пока­заться, что фрейм должен быть расположен справа от двух существующих фреймов, однако это не так. Причина подобного поведения диспетчера ком­поновки состоит в том, что фрейм .two занимает всю нижнюю часть полости, несмотря на то, что его размеры по горизонтали меньше размеров полости.

Где будет расположена полость после выполнения дан­ного примера? Конечно же, она располагается слева от фрейма .three, ко­торый последним был обработан диспетчером компоновки с выравниванием типа right и выше фрейма .two, который последним был обработан с вы­равниванием типа bottom. Данный пример объясняет, почему отсутствуют различия между двумя предыдущими примерами, в одном из которых для .one.gamma был указан тип выравнивания left, а для .one.right — тип вы­равнивания right. В данном случае выравнивание по левому и по правому краю полости дает одинаковый результат. Однако, если в том же фрейме по­явится дополнительный компонент, внешний вид окна для разных конфигу­раций будет различаться. Задайте после выполнения сценариев, представлен­ных в примерах 3.3 и 3.4, следующие две команды, и различия отобразятся на экране:

button .one.omega -text omega

      pack .one.omega -side right

Каждый из родительских фреймов содержит свою полость, поэтому для реализации сложного взаимного расположения компонентов приходится при­бегать к помощи вложенных фреймов. Если внутри каждого фрейма исполь­зуется выравнивание только по горизонтали или только по вертикали, вы сможете без труда предсказать, каким будет внешний вид окна.

Пространство компоновки и пространство отображения. Выполняя действия по упорядочению компонентов, диспетчер компонов­ки оперирует понятиями пространства компоновки и пространства отображе­ния. Пространство отображения — это область, необходимая компоненту для того, чтобы он мог быть представлен на экране. Пространство компоновки — это область, которую диспетчер компоновки выделяет для этого компонента. Из-за особенностей размещения на экране для компонента может быть выде­лена область большая или меньшая, чем необходимо. Лишнее пространство отсчитывается вдоль координаты, по которой выравнивается компонент.

Опция –fill .Если при вызове диспетчера компоновки указана опция —fill, компонент будет занимать все доступное для него пространство. Заполнение может вы­полняться по оси X, Y или по обеим координатам. По умолчанию заполнение не производится. Именно поэтому в рассмотренных ранее примерах на экране был виден черный фон главного окна (пример 3.6).

Пример 3.6.

frame   .one  -width 100  -height 50  -bg grey50

frame   .two  -width 40 -height 40  -bg white

# Компоновка при разрешенном заполнении

pack  .one   .two —side bottom —fill x

 frame   .three -width 20 -height 20 -bg red

 pack  .three -side right -fill x

Представленный в примере 3.6. код очень похож на код примера, приведенный в примере 3.5, за исключением того, что для всех фреймов задана опция —fill х. Фрейм .two заполняет свободную область, а фрейм .three — нет. Такое различие в поведении фреймов связано с тем, что операция заполнения не затрагивает полость. В данном случае полость — это область окна, окрашенная в черный цвет. С другой стороны, фрейму . two выделена вся область от левой до правой границы окна, поэтому данный фрейм может быть расширен. Фрейму .three выделена только правая часть верхней полосы окна, в результате заполнение по координате X не дает никакого эффекта.

Операцию заполнения удобно применять при формировании панелей ин­струментов. Предположим, что кнопки надо разместить на обоих краях фрей­ма, а между ними должна остаться свободная область. Фрейм, содержащий кнопки, располагается в верхней части окна. Кнопки выровнены по левому и по правому краю фрейма. Без заполнения произошло бы сжимание фрейма, и кнопки были бы расположены вплотную одна к другой. Если же объявлено заполнение по координате X, панель инструментов заполняет всю верхнюю часть окна.

frame .menubar -bg white

frame .body -width 150 -height 50 -bg grey50

          # Кнопки располагаются на разных концах панели инструментов
foreach b {alpha beta} {

button .menubar.$b -text $b >

pack .menubar.alpha -side left pack .menubar.beta -side right

  • Опция —fill позволяет панели инструментов располагаться
  • в верхней части окна на всю его ширину
    pack .menubar —side top —fill x

pack .body

Внутреннее дополнение, задаваемое с помощью опций —ipadx и –ipady. Расширить область, занимаемую компонентом, можно также, используя опции —ipadx и —ipady команды pack. Эти опции запрашивают дополнитель­ное пространство по оси X и по оси Y. Наличие ограничений может привести к тому, что запрос не будет удовлетворен, но, как правило, данные опции позволяют расширить область отображения компонента. Пример, приведен­ный в примере 3.7 , похож на пример, рассмотренный ранее. Различие лишь в использовании внутреннего дополнения.

          Пример 3.7.

          # Создание и размещение двух фреймов
frame  .menubar —bg white

frame  .body -width 150 -height 50 -bg grey50

          # Кнопки располагаются на разных концах панели инструментов
foreach b {alpha beta} {

button  .menubar.$b -text $b }

pack  .menubar.alpha -side left -ipady 10 pack  .menubar.beta -side right -ipadx 10

          # Let the menu bar fill along the top
pack  .menubar -side top -fill x -ipady 5
pack  .body

Кнопка alpha превосходит по высоте кнопку beta, а кнопка beta шире, чем кнопка alpha. Внутреннее дополнение применяется и при компоновке фрейма, что, с одной стороны, уменьшает размеры полости, а с другой сто­роны, формирует дополнительную свободную область над кнопками и под ними.

Для некоторых компонентов предусмотрены атрибуты, управляющие раз­мерами области отображения. Поэтому трудно, например, отличить фрейм, для которого задана ширина 50 пикселей и не указано внутреннее дополне­ние, от фрейма, для которого указаны опции —width 40 и —ipadx 5. И в том и в другом случае ширина области отображения будет равна 50 пикселям.

Опции —padx и —pady предусмотрены также и для кнопок. При исполь­зовании этих опций размеры области отображения, занимаемой кнопками, увеличиваются. При работе с кнопками дополнение обычно используется для того, чтобы обеспечить интервал между текстом, отображаемым на кнопке, и ее краями. Различие между кнопками с внутренним отображением и без него демонстрирует код, приведенный в примере 3.8. Опция -anchor e ука­зывает на то, что текст должен размещаться в правой части кнопки.

Пример 3.8.

  • Компонент foo получает внутреннее дополнение от диспетчера компоновки

button  .foo  -text Foo  -anchor e -padx 0 -pady 0

 pack  .foo -side right  -ipadx 10 -ipady 10

#Для компонента bar задано собственное внутреннее дополнение
button  .bar -text Bar -anchor e -pady 10 -padx 10

pack  .bar -side right  -ipadx 0 -ipady 0

При указании дополнений используется единица измерения длины обла­сти отображения, допустимая в Тк. Обычное числовое значение интерпре­тируется как количество пикселей. Если за числом следует i, m, с или р, то предполагается соответственно расстояние в дюймах, миллиметрах, санти­метрах или пунктах.

Внешнее дополнение, задаваемое с помощью опций —padx и –pady. Диспетчер компоновки может реализовать внешнее дополнение, т.е. ре­зервировать область компоновки, в которой не могут размещаться никакие элементы. Это пространство выделяется за пределами обрамления компонен­та, используемого для эмуляции трехмерных элементов.  Для формирования кнопки по умолчанию используются дополнительный фрейм и внешнее дополнение.

. config -borderwidth 10

# Кнопка 0К является кнопкой по умолчанию

frame .ok -borderwidth 2 -relief sunken

button .ok.b -text OK

pack .ok.b -padx 5 -pady 5

# Cancel представляет собой обычную кнопку

button  .cancel -text Cancel

pack   .ok   .cancel  -side left  -padx 5  -pady 5

Внешний вид кнопки .ok.b не изменился бы даже в том случае, если бы при вызове команды pack была указана опция —fill both. Дочерний компо­нент не заполняет область дополнения.

Для кнопки по умолчанию  в Тк 8.0 был реализован атрибут default. Он реализует отображение кнопки по умолчанию, принятой для текущей платформы. В системе Unix кнопки по умолчанию выглядят приблизительно так, как показано на рисунке, а в системах Macintosh и Windows их внешний вид несколько отличается.

В Тк 8.4 была добавлена возможность создавать асимметричное допол­нение, указывая в качестве значения опции список из двух элементов. На­пример, в приведенном ниже выражении добавляется по 5 пикселей слева и справа от компонентов, 3 пикселя выше них и 6 пикселей под ними.

pack  .ok  .cancel -side left  -padx 5 -pady {3 6}

Изменение размеров окон и опция –expand. Опция —expand true диспетчера компоновки позволяет расширять компо­нент так, чтобы он занимал невостребованную полость. В примере 25.6 был приведен пример создания фрейма в верхней части окна, который распро­странялся на всю ширину окна, независимо от того, что при вызове команды pack была указана опция —side right. Рассмотрим более общий случай — окно с изменяемыми размерами. Когда пользователь увеличивает окно, ком­поненты могли бы занять дополнительное пространство. Предположим, что какой-то из компонентов, например текстовый компонент, список или холст, находится во фрейме, снабженном полосами прокрутки. Этот фрейм должен расширяться, занимая свободную область в родительском фрейме (например, в главном окне), а компонент (например, холст) должен занимать свободную область, возникшую во фрейме с полосами прокрутки.

Опция —fill both практически всегда используется с опцией —expand true, поэтому компоненты расширяются на свободную область компоновки. Обратное утверждение неверно. Во многих случаях компонент должен был бы заполнить полость, но не предпринимает попытки к расширению. Раз­личия между этими двумя случаями демонстрируют примеры, приведенные ниже.

Теперь рассмотрим, что произойдет при увеличении окна. Начало следую­щего примера  3.9 напоминает пример, приведенный в листинге 3.7, но размеры главного окна увеличиваются.

      Пример 3.9.

# Для главного окна задается черный цвет

.   config —bg black

# Создание и компоновка двух фреймов

frame   .menubar -bg white

frame   .body -width 150  -height 50 -bg grey50

# Кнопки размещаются в разных концах панели инструментов

foreach b {alpha beta} {

button   .menubar.$b -text $b }

pack  .menubar.alpha -side left pack  .menubar.beta -side right

# Панель инструментов заполняет пространство по ширине окна
pack  .menubar —side top —fill x

pack  .body

# Увеличение размеров главного окна

wm geometry  .  200×100

# Интерактивное изменение размеров разрешается

vm minsize  . 100  50

Появившееся пространство занимает только компонент .menubar, посколь­ку при вызове команды pack была указана опция —fill x. Для того чтобы фрейм .body вел себя подобным образом, надо изменить команду pack так, как показано в примере 3.10.

          Пример 3.10

  • Выполняются все действия, предусмотренные в примере 3.9,
  • затем к .body применяется команда pack
    pack .body -expand true -fill both

Если расширение разрешено для нескольких компонентов, являющих­ся дочерними по отношению к одному родительскому компоненту, диспет­чер компоновки пропорционально распределяет между ними дополнительное пространство. В рассматриваемом примере такой подход вряд ли уместен. В частности, для .menubar расширение задавать не следует.

  • Выполняются все действия, предусмотренные в примере 3.9,
  • затем к .menubar и  .body применяется команда pack
    pack .menubar -expand true -fill x

pack  .body -expand true -fill both

Фиксация. Если для компонента выделено большее пространство компоновки, чем требуется для его отображения, вы можете размещать компонент в преде­лах этого пространства с помощью опции —anchor, задаваемой при вызове команды pack. Значения данной опции принято называть якорями. По умол­чанию предполагается фиксация по центру области. Остальные значения оп­ции —anchor (n, ne, e, se, s, sw, w и nw) ориентируют компонент «по компасу», т.е. задают направление «север», «северо-восток», «восток» и т.д.

# Для главного окна задается черный цвет

 .   config —bg black

         #Два фрейма создаются так, что полость остается свободной

         frame .prop -bg white -height 80 -width 20

frame .base -width 120 -height 20 -bg grey50 pack .base -side bottom

#Размещение в полости текстовой метки и компонента .prop
label .foo —text Foo

pack .prop .foo -side right -expand true

Фрейм .base выравнивается по нижней части окна. Затем фрейм .prop и текстовая метка .foo выравниваются по правой части окна; при этом зада­ется опция —expand true, но опция —fill не указывается. Вместо того чтобы разместить компоненты как можно ближе к правому краю, опция —expand выделяет каждому из компонентов половину области, свободной после вклю­чения компонента .base. Область делится линией, перпендикулярной оси X. Поскольку опция —anchor не указана, по умолчанию предполагается, что для нее задано значение center. Пример, приведенный в примере 3.11, демон­стрирует другие способы фиксации компонента.

Пример 3.11

.   config —bg black

#Два фрейма создаются так,  что полость остается свободной
frame   .prop  —bg white —height 80  —width 20

frame   .base  -width 120  -height 20 -bg grey50 pack  .base -side bottom

  • Размещение в полости текстовой метки и компонента .prop.
  • Позиции данных компонентов уточняются с помощью якорей
    label .foo —text Foo

pack  .prop -side right -expand true -anchor sw pack .foo -side right -expand true -anchor ne

Свободное пространство присутствует как по бокам текстовой метки, так: сверху и снизу от нее. Фрейм .prop может перемещаться только вдоль си X, поэтому для него доступны лишь три позиции: левая, центральная, правая. Любое из значений, w, nw и sw, опции —anchor приводит к тому, что фрейм будет расположен в левой части области. Значение center, n или s располагает фрейм по центру. И, наконец, если опция —anchor имеет значение е, se или пе, фрейм будет расположен в правой части области.

Если вы хотите просмотреть все варианты фиксации компонентов, за­пустите на выполнение фрагмент кода, приведенный в примере 3.12. Ко­манда update idletasks принудительно выполняет отложенные операции отображения. Команда after 500 переводит сценарий в режим ожидания на 500 миллисекунд.

Пример 3.12.

foreach anchor {center n ne e  se s sw w nw center} {

 pack  .foo   .prop -anchor $anchor

  • Обновление отображения
    update idletasks
  • Ожидание в течение 500 миллисекунд
    after 500}

Очередь компоновки. Диспетчер компоновки поддерживает порядок очередности, в котором до­черние компоненты помещаются во фрейм. Набор компонентов, включаемых в состав родительского окна, называют очередью компоновки. По умолча­нию очередной дочерний компонент добавляется в конец очереди компонов­ки. В результате первый из дочерних компонентов оказывается ближе дру­гих к тому краю окна, который указан в качестве значения опции —side. Опции диспетчера компоновки —before и —after позволяют управлять оче­редью компоновки, а также дают возможность изменять порядок следования тех компонентов, которые уже включены в родительский фрейм.

#В цикле создаются пять текстовых меток
foreach label {one two three four five} {

label   .$label -text $label pack  .$label -side left  -padx 5 }

#Процедура ShuffleUp перемещает компонент в начало очереди
proc ShuffleUp { parent child } {

set first [lindex [pack slaves $parent] 0]

pack $child -in $parent -before $first }

# Процедура ShuffleDown перемещает компонент в конец очереди

proc ShuffleDown { parent child } {

pack $child -in $parent }

ShuffleUp  .  .five

ShuffleDown   .  .three

Интроспекция. Команда pack slaves возвращает список дочерних компонентов. Компо­ненты в списке расположены в том же порядке, что и в очереди компоновки. Процедура ShuffleUp использует команду pack slaves для того, чтобы выде­лить тот дочерний компонент, перед которым необходимо включить допол­нительный элемент. Процедура ShuffleDown реализована несколько проще, поскольку по умолчанию компоненты добавляются в конец очереди компо­новки.

При повторной обработке диспетчером компоновки компонент сохраняет параметры, определяющие расположение в окне, которые были заданы ра­нее. Чтобы просмотреть текущие параметры компоновки компонента, надо использовать команду pack info.

pack info .five

=> -in . -anchor center -expand 0 -fill none -ipadx 0  -ipady 0 -padx 0 -pady 0 -side left

Выбор родительского компонента при компоновке. Практически во всех примерах, приведенных в данной главе, компонен­ты при компоновке размещаются в родительском фрейме. Однако компо­нент можно включить в состав любого из потомков этого фрейма. Напри­мер, компонент .а.b может быть скомпонован в составе .а, .а.с, .a.d.e.f и т.д. Опция — in команды pack позволяет указать альтернативный родитель­ский компонент для компоновки. Решение изменить родительский элемент может быть принято из-за того, что иерархия, обеспечивающая оптимальное размещение компонентов, привела бы к появлению важных компонентов со слишком сложными именами. В примере 3.4 использовались имена кнопок .one.alpha и .one.right .delta, которые плохо согласуются между собой. Ниже приведена альтернативная реализация того же примера, в котором тот же результат получается при использовании более простых имен кнопок.

Пример 3.13. Использование альтернативных родительских компонентов

 при компоновке

#Создание и компоновка двух фреймов
frame   .one —bg white

frame   .two -width 100 -height 50 -bg grey50

#Создание набора кнопок
foreach b {alpha beta} {

button .$b -text $b pack ,$b -in .one -side left }

#Создание фрейма для двух дополнительных кнопок
frame   .one.right

foreach b {delta epsilon} {

button .$b -text $b

pack .$b -in .one.right -side bottom }

pack  .one.right  -side right pack  .one   .two  -side top

Используя подобный подход, следует помнить, что порядок создания ком­понентов имеет большое значение. Фреймы надо создавать в первую очередь и лишь после этого определять компоненты, которые.

Правила компоновки. Работая с диспетчером компоновки pack, надо соблюдать следующие правила:

  • Все элементы в одном фрейме должны быть скомпонованы либо по вертикали (опции —side top и —side bottom), либо по горизонтали (опции —side left и —side right). Объединяя различные типы выравнивания очень трудно добиться требуемых результатов. Если вам надо реализовать сложное взаиморасположение компонентов, используйте дополни­тельные фреймы.
  • По умолчанию диспетчер компоновки pack помещает компоненты в их родительский фрейм. Родительский фрейм должен быть создан ранее, чем компоненты, предназначенные для размещения в нем.
  • Если вы включаете компоненты в другие фреймы, необходимо помнить о том, что фреймы должны быть созданы раньше компонентов и рас­положены в стеке окон ниже их.
  • По умолчанию диспетчер  компоновки  игнорирует  атрибуты  width и height фреймов, в которых должны быть расположены компонен­ты. Размеры фрейма изменяются так, чтобы в нем могли поместиться все требуемые компоненты. Для того чтобы отключить автоматическое изменение размеров, надо использовать команду pack propagate.
  • При работе диспетчера компоновки используются понятия простран­ство компоновки и пространство отображения. Компонент не обязатель­но занимает все пространство компоновки, выделенное ему.
  • Опция —fill разрешает заполнение пространства компоновки по оси X, по оси Y или в обоих направлениях.
  • Опция —expand true задает расширение пространства компоновки на те части полости, которые в противном случае оставались бы невостребо­ванными. Если на дополнительное пространство претендует несколько компонентов, это пространство распределяется пропорционально меж­ду ними.
  • Опции —ipadx и —ipady резервируют дополнительное пространство отоб­ражения в пределах объекта. Это пространство выделяется только в том случае, если есть реальная возможность сделать это.
  • Опции —padx и —pady резервируют дополнительное пространство компо­новки за пределами компонента. Пространство выделяется только в том случае, если есть реальная возможность сделать это. Компонент ни при каких условиях не заполняет пространство, выделенное посредством оп­ций —padx и —pady. Для выделения областей разного размера в качестве значения опции можно указать список из двух элементов (эта возмож­ность реализована в Тк 8.4).

Команда pack. В таблице 3.1 приведены основные сведения о команде pack. В табл. 3.2 описаны опции, управляющие компоновкой компонента. Эти опции указы­ваются при вызове команды pack configure, а для получения информации о текущих установках применяется команда pack info.

Таблица 3.1. Команда pack

pack win ?окно ..? ?опции? Выполняет те же действия, что и pack configure
pack configure окно ?

окно   …? ?опции?

Выполняет компоновку одного или более компонен­тов, используя опции, описанные в табл. 3.2
pack forget окно  ?окно . . . ? Удаляет указанные окна из очереди компоновки
pack info окно Возвращает параметры компоновки для указанного окна
pack propagate окно ?логическое_значение? Запрашивает или задает режим согласования разме­ров для окна, в котором содержатся другие компо­ненты
pack slaves окно Возвращает список компонентов, управляемых ука­занным окном

 

Таблица 3.2. Опции команды pack

—after окно Размещение после указанного окна в стеке
—anchor якорь Значение опции —anchor, или якорь, может быть одним из следующих: center, n, ne, e, se, s, sw, w или nw
—before окно Размещение перед указанным окном в стеке
—expand

логическое_ значение

Управляет расширением на невостребованные части по­лости
—fill  стиль Управляет заполнением пространства компоновки. В ка­честве стиля могут быть указаны следующие значения: х, у, both или попе
—in окно Размещение в пределах окна
—ipadx размер Внутреннее    дополнение    по    горизонтали.    Задается в экранных единицах измерения
—ipady размер Внутреннее дополнение по вертикали. Задается в экран­ных единицах измерения
—padx размер Внешнее дополнение по горизонтали. Задается в экран­ных единицах измерения. Значение опции может пред­ставляет собой список из двух элементов; в этом случае осуществляется асимметричное дополнение
—pady размер Внешнее дополнение по вертикали. Задается в экранных единицах измерения. Значение опции может представ­ляет собой список из двух элементов; в этом случае осу­ществляется асимметричное дополнение
—side выравнивание В качестве значения опции могут быть заданы следую­щие типы выравнивания: top, right, bottom или left

Стек окон. Для управления расположением элементов в стеке окон используются ко­манды raise и lower. Позиция элементов в стеке окон определяет их отоб­ражение на экране. Окна, занимающие более высокое положение в стеке, за­крывают окна, расположенные ниже. По умолчанию новые окна создаются в верхней части стека и располагаются поверх окон, созданных ранее. Рас­смотрим приведенные ниже команды.

button  .one

frame .two

pack  .one -in  .two

Если вы выполните эти команды, кнопка не будет отображаться на экране. Причина в том, что фрейм занимает более высокое положение в стеке и за­крывает кнопки. Изменить порядок следования окон в стеке позволяет ко­манда raise, raise  .one  .two

Приведенная выше команда располагает окно .one непосредственно над окном .two. Если второй параметр не указан, окно .one будет помещено в вершине стека. Команда lower имеет тот же формат. Если при ее вызо­ве указывается один параметр, окно помещается ниже всех остальных окон в стеке. В противном случае оно располагается непосредственно под окном, указанным в качестве второго параметра.

Команды raise и lower можно применять к окнам верхнего уровня, управ­ляя тем самым их взаимным расположением. Например, если пользователю понадобилось диалоговое окно, которое уже было отображено ранее, вы мо­жете использовать команду raise, чтобы разместить это окно поверх других на рабочем столе. Для того чтобы определить взаимное расположение окон верхнего уровня в стеке, надо использовать команду wm stackorder.

Диспетчер компоновки grid.

Размещает компоненты в виде таблицы с изменяющимися размерами строк и столбцов. Вы задаете строки и столбцы, занимаемые компонентами, а размеры ячеек автоматически подбираются так, чтобы в них могли поместиться все необходимые компоненты. Данный тип диспетчера очень удобен для представления данных в виде таблиц. Кроме того, этот диспетчер предоставляет средства для управления размерами строк и столбцов, а также для динамического изменения размеров таблицы. Объявляя вложенные фреймы и связывая с ними свои диспетчеры компоновки, вы можете реализовать достаточно сложные конфигурации компонентов на экране.

Не следует применять диспетчеры раcк и grid к одному и тому же компоненту. При формировании пользовательского интерфейса можно использовать как диспетчер pack, так и диспет­чер grid. Однако для размещения дочерних элементов конкретного компонента можно использовать только один диспетчер.

Размещение компонентов в виде таблицы. В примере 3.14 показан пример использования диспетчера компоновки —d для размещения набора текстовых меток и фреймов в виде таблицы. При этом используется возможность относительной компоновки, предоставляемая данным диспетчером. Вместо того чтобы явно объявлять строки и столбцы, мы будем формировать таблицу, исходя из порядка следования команд grid и размещения их компонентов. Каждая команда grid создает новую стро­ку, а указанные в ней компоненты формируют столбцы. В данном примере таблица состоит из двух столбцов; при каждой итерации цикла к ней добав­ляется новая строка. Диспетчер компоновки grid создает столбцы размера, достаточного для включения наибольшего компонента. Компоненты меньших размеров располагаются по центру ячеек. Именно по этой причине текстовые метки в рассматриваемом примере выровнены по центру.

Пример 3.14.

foreach color {red orange yellow green blue purple} {

label  .l$color -text $color -bg white

frame  .f$color -background $color -width 100 -height 2

grid .l$color  .f$color }

Опция –sticky. Если размер ячейки оказывается больше, чем размер содержащегося в ней компонента, вы можете изменять размеры и размещение компонента, зада­вая опцию —sticky. Данная опция объединяет функциональные возможности опций —fill и —anchor диспетчера компоновки pack. С помощью этой опции вы можете указать, с какой из границ ячейки должен непосредственно со­прикасаться компонент. В качестве значения опции —sticky допустимо любое сочетание букв n, e, w и s. Соответственно размеры и расположение компонен­та будут изменяться так, чтобы он непосредственно соприкасался с верхней, правой, левой и нижней границами ячейки. Вы можете использовать конкате­нацию указанных выше букв (например, news) либо разделять их пробелами или запятыми (например, n,e,w,s). В примере 3.15 опция —sticky w изменя­ет расположение текстовой метки и выравнивает ее по левому краю ячейки. Опция —sticky ns растягивает закрашенный фрейм так, что он занимает по высоте всю строку.

Пример 3.15.

reach color {red orange yellow gr

een blue purple}  { label   .l$color -text $color -bg white frame   .f$color  -background $color -width  100 -height  2 grid   .l$color   .f$color grid .l$color -sticky w grid  .f$color -sticky ns

В примере, представленном в примере 3.15, команда grid используется двумя способами. Первый раз она вызывается для определения позиций компонентов. Далее эта же команда модифицирует существующие параметры; поскольку распределения компонентов по столбцам и строкам таблицы уже известно, при вызове grid задается лишь опция —sticky.

Позиции компонентов в строках и столбцах таблицы можно указать непосредственно с помощью атрибутов row и column. При этом приходится затрачивать дополнительные усилия по сравнению с относительной компоновкой, но в ряде случаев это приходится делать.

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

Пример 3.16.

set row 0

foreaich color {red orange yellow green blue purple} {

label   .l$color -text $color -bg white

frame  .f$color -background $color -width 100

grid  .l$color -row $row -column 0 -sticky w

grid .f$color -row $row -со1шт 1 -sticky ns

incr row

Внешнее дополнение, реализуемое с помощью опций —padx и –pady. Задавая опции —padx и —pady, можно указать размер свободной облас между компонентом и границами ячейки. В примере 3.17 с помощью внешнего дополнения реализуется отступ текстовых меток от левого края таблиц а также задается свободное пространство между цветными полосами.

Пример 3.17.

foreach color {red orange yellow green blue purple} {

label   .l$color  -text $color -bg white

frame   .f$color -background $color -width  100  -height  2

grid   .l$color  .f$color grid  .l$color -sticky w -padx 3

grid  .f$color -sticky ns -pady 1

В Tk 8.4 разработчику была предоставлена возможность создавать асим­метричное дополнение, указывая в качестве значения опции список из двух элементов. Например, опция —padx {0.125i 0.25i} определяет слева от ком­понента свободное пространство размером 1/8 дюйма, а справа — простран­ство размером 1/4 дюйма.

Внутреннее дополнение, реализуемое с помощью опций —ipadx и –ipady. Применяя внутреннее дополнение, вы можете предоставить компоненту большее пространство отображения, чем он обычно занимает. При использо­вании внутреннего дополнения размеры таблицы увеличиваются. В отличие от —ipadx и —ipady. опция —sticky позволяет растянуть некоторые компо­ненты, но при этом размеры таблицы останутся неизменными. В примере, приведенном в примере 3.18, благодаря использованию опции —ipady высота текстовых меток увеличивается.

Пример 3.18.

roreach color {red orange yellow green blue purple} {

 label .l$color -text $color -bg white

frame .f$color -background $color -width 100 -height 2

grid .l$color .f$color grid .l$color -sticky w -padx 3 -ipady 5

grid .f$color -sticky ns -pady 1

Размещение нескольких компонентов в одной ячейке. Фрагмент кода, приведенный в примере 3.19, демонстрирует различные значенияения опции —sticky. При этом используется возможность размещения нескольких компонентов в одной ячейке таблицы. В данном случае в каждую ячейку помещается квадратный фрейм, после чего в той же ячейке располагается текстовая метка. Для меток, находящихся в разных ячейках, заданы различные значения опции —sticky. Необходимо следить за тем, чтобы фрейм был создан первым, иначе он будет закрывать метку. Опции —padx и —pady создают внешнее заполнение и тем самым формируют зазор между меткой и границами ячейки.

Пример 3.19.

set  index 0

foreach x {news ns ew » » new sew wsn esn nw ne sw se n s w e} {

frame .f$x -borderwidth 2 -relief ridge -width 40 -height 40

grid .f$x -sticky news -row [expr {$index/4}] -column [expr {$index°/,4}]

label .l$x -text $x -background white

grid .l$x -sticky $x -padx 2 -pady 2 \ -row [expr {$index/4}] -column [expr {$index%4>]

incr index}

Объединение строк и столбцов. Компонент может занимать несколько ячеек. Число строк и столбцов, не­обходимых для размещения компонента, задается с помощью опций -rowspan и -columnspan. В примере 3.20 приведен пример использования опций row. column, rowspan и columnspan.

Пример 3.20.         

. config -bg white

foreach color {888 999 aaa bbb ccc fff} {

frame .$color -bg #$color -width 40 -height 40}

         grid      .888 -row 0 -column 0 -columnspan 3 -sticky news

         grid      .999 -row 1 -column 0 -rowspan 2 -sticky news

         grid      .aaa -row 1 -column 1 -columnspan 2 -sticky news

         grid      .bbb -row 2 -column 2 -rowspan 2 -sticky news

          grid      .ccc -row 3 -column 0 -columnspan 2 -sticky news

          grid      .iff -row 2 -column 1 -sticky news

При выполнении команды grid, в которой размещение управляется по­рядком следования компонентов, бывает необходимо объединять строки или столбцы либо оставлять свободными ячейки. Для этой цели предусмотрены специальные символы.

Символ — задает объединение столбцов.

Символ ^ задает объединение строк.

Символ х указывает на то, что ячейка должна быть пропущена.

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

Пример 3.21.

. config -bg white

      foreach color {888 999  aaa bbb ccc ddd iff} {
frame .$color -bg #$color -width 40 -height 40}

     grid .888 —     —     -sticky news

     grid .999 .aaa  —   -sticky news

     grid ^   . fff  .bbb -sticky news

     grid .ccc —     ^     -sticky news

Атрибуты строк и столбцов. Диспетчер компоновки grid поддерживает атрибуты, задаваемые для це­лой строки или столбца. Эти атрибуты управляют размерами соответствую­щих ячеек. Для установки атрибутов или определения их текущих значений используются операции grid rowconfigure и grid columnconfigure.

grid columnconfigure окно столбец ?атрибуты?

grid rowconfigure окно строка ?атрибуты?

Если атрибуты не заданы, возвращается информация о текущих установ­ках. В качестве второго параметра может быть задан список, что позволяет одновременно изменять атрибуты нескольких строк или столбцов.

Дополнение строк и столбцов. Атрибут —pad увеличивает размер ячеек в строке или в столбце. Перво­начально размер ячеек определяется наибольшим компонентом. Опция —pad увеличивает эти размеры. Если даже ячейка увеличена, существует возмож­ность заполнения ее компонентом.  Сделать это позволяет опция —sticky.

Дополнение строк и столбцов можно сравнить с внутренним дополнением компонентов, так как выделенное пространство может быть заполнено. Для сравнения, атрибуты padx и pady компонента создают пустое пространство между ним и границами ячейки. Это пространство не подлежит заполнению. В пример 3.22 показано различие между дополнением строки или столбца и дополнением компонента. Дополнение строки увеличивает ее высоту, в то время как дополнение компонента . f1 отделяет границы компонента от гра­ниц ячейки.

Пример 3.22.

.   config -bg black

label   .fl  -text left  -bg #ccc

label   Л2 -text right  -bg #aaa

         grid  .fl   .f2 —sticky news        ;# дополнение отсутствует

         grid  .fl —padx 10 —pady 10     ;# дополнение для ячейки

grid rowconfigure  .   0 —pad 20         ;# дополнение для строки

Минимальный размер ячейки. Опция —minsize ограничивает минимальные размеры ячеек, принадлежа­щих строке или столбцу. Размеры строк или столбцов могут увеличиваться с увеличением содержащихся в них компонентов, но не могут стать мень­ше указанной величины. Опция —minsize полезна при формировании пустых строки и столбцов. Такой подход более эффективен, чем создание дополни­тельного фрейма.

Поддержка окон с изменяемыми размерами. Если размеры родительского окна больше, чем необходимо для отображе­ния таблицы, окно сжимается до требуемых размеров. Запретить изменение размеров окна можно с помощью команды grid propagate. В этом случае таблица будет размещаться по центру окна. Если размеры окна настолько малы, что в нем не помещается таблица, она фиксируется в левом верхнем углу окна, а фрагменты, выступающие вправо и вниз за границы окна, не отображаются.

По умолчанию при увеличении родительского фрейма размеры строк и столбцов остаются постоянными. Задать изменение размеров строки или столбца можно с помощью опции —weight. Значением этой опции является целое число больше нуля. В примере 3.23 показаны текстовый компонент и две полосы прокрутки, обработанные диспетчером компоновки grid. Текстовый компонент находится в нулевом столбце нулевой строки и может расширяться в обоих направлениях. Вертикальная полоса прокрутки расположена в первом столбце нулевой строки, и размеры ее мо­гут изменяться только в направлении Y. И, наконец, горизонтальная полоса прокрутки находится в нулевом столбце первой строки, поэтому размеры ее могут изменяться только в направлении X.

            Пример 3.23.

text   .text  -yscrollcommand «.yscroll set» -xscrollcommand «.xscroll set»-width 40 -height  10

              scrollbar   .yscroll  -command «.text yview»   -orient vertical

  scrollbar  .xscroll  -command «.text xview»  -orient horizontal

  grid  .text   .yscroll -sticky news grid  .xscroll  -sticky ew

  grid rowconfigure   .  0 -weight  1

  grid columnconfigure   .   0 -weight  1

Для того чтобы размеры строк или столбцов по-разному изменялись при увеличении родительского окна, надо задать для них различные веса. Однако этой возможностью надо пользоваться аккуратно, так как изменение разме­ров происходит только при наличии дополнительного пространства. Пред­положим, например, что четыре столбца таблицы имеют ширину 10, 20, 30 и 40 пикселей. Таким образом, общая их ширина составляет 100 пикселей. Ес­ли ширина родительского окна возрастет до 140 пикселей, окажется, что для отображения таблицы есть 40 дополнительных пикселей. Если для каждого столбца был задан вес 1, каждый из них получил бы по 10 пикселей дополни­тельного пространства. Теперь предположим, что для столбца 0 задан вес 0, для столбцов 1 и 2 — вес 1 и для столбца 3 — вес 2. Тогда с увеличением раз­меров родительского окна столбец 0 не будет увеличиваться, столбцы 1 и 2 получат по 10 дополнительных пикселей и столбец 3 увеличится на 20 пик­селей. В большинстве случаев применяются веса, равные 0 или 1.

При сжатии окна наличие весов приводит в возникновению обратного эффекта. Если строка или столбец должны сжиматься, вес определяет сте­пень сжатия. Строки и столбцы сжимаются тем больше, чем боль­шие значения весов для них заданы. Предположим, например, что с помощью диспетчера компоновки grid два одинаковых фрейма одинакового размера размещены в двух столбцах таблицы. Когда пользователь увеличивает размеры окна, фрейм в столбце, которо­му соответствует больший вес, увеличивается с большей скоростью. Если окно уменьшается, то этот фрейм также уменьшается быстрее другого.

Опция –uniform. Опция -uniform упрощает создание столбцов (или строк) одинаковой ши­рины (высоты). С помощью данной опции создается группа столбцов или строк. Значение опции может быть произвольным (например, xyz). Считает­ся, что все столбцы (или строки) с одинаковым идентификатором, заданным с помощью опции —uniform, принадлежат одной и той же группе. Если для них задано одно и то же значение опции —weight, размеры их будут одина­ковыми. Если же, например, один из столбцов или одна из строк в группе имеет вес, вдвое превышающий вес других столбцов (или строк), то этот столбец (или строка) будет вдвое больше остальных. Пример использования различных весов при работе с компонентами из одной группы показан в ли­стинге 3.24.

Пример 3.24.

foreach x {alpha beta gamma x у z} {

label   .$x -text $x }

beta config -bg white                                           

.y config -bg white

grid .alpha .beta .gamma -sticky news

grid .x .y . z -sticky news

grid columnconfigure . «0 1 2» -uniform groupl -weight 1

erid columnconfiffure . 1 —weight 2

В таблице 3.3 приведены основные сведения о команде grid. В таблице 3.4 перечислены опции, которые задаются при вызове команды grid configure.

 

Таблица 3.3. Команда grid

grid bbox окно

? столбец_1 строка_1? ?столбец_2 строка_2?

Возвращает ограничивающий прямоугольник для всей таблицы, для ячейки, находящейся на пересе­чении указанных столбца и строки, либо ячеек, на­ходящихся в заданном диапазоне
grid columnconfigure окно столбец опции? Устанавливает   либо   запрашивает   конфигурацию столбца. При вызове команды могут быть заданы опции —minsize, —weight, —pad и –uniform
grid configure окно ?окно   …? ?опции? Выполняет компоновку одного или нескольких ком­понентов. Детали компоновки задаются с помощью опций, описанных в табл. 3.4
grid forget окно  ?окно Удаляет указанные окна из стека
grid info окно Возвращает опции, использованные при компоновке указанного окна
grid location окно х у Возвращает номер столбца и строки той ячейки, ко­торой принадлежат точки х, у в указанном окне
grid propagate окно

?логическое_значение?

Разрешает или запрещает согласование размеров окна
grid rowconfigure

окно строка ?опции?

Устанавливает   либо   запрашивает   конфигурацию строки. При вызове команды могут быть заданы оп­ции —minsize, —weight, —pad и –uniform
grid remove компонент Отменяет компоновку компонента, но запоминает его конфигурацию
grid size окно Возвращает число столбцов и строк
grid slaves окно  ?-row строка? ?-column столбец? Возвращает список либо всех компонентов, содер­жащихся в окне, либо тех из них, которые находятся в указанной строке или столбце

Таблица 3.4. Опции, используемые при компоновке с помощью диспетчера grid

—in окно Размещение в указанном окне
—column столбец Номер столбца. Отсчет столбцов начинается с нуля
—columnspan л Объединение п столбцов
—ipadx число„пикселей Внутреннее дополнение компонента по горизонтали
—ipady число_пикселей Внутреннее дополнение компонента по вертикали
—padx число_пикселей Внешнее  дополнение   компонента  по   горизонтали. Значение данной опции может представлять собой список из двух элементов. В этом случае осуществ­ляется несимметричное дополнение
-pady число_пикселей Внешнее дополнение компонента по вертикали. Зна­чение данной опции может представлять собой спи­сок из двух элементов. В этом случае осуществляется несимметричное дополнение
-row строка Номер строки. Отсчет строк начинается с нуля
-rowspan n Объединение п строк
-sticky границы Позиционирование компонента путем указания любо­го сочетания северной (п), южной (s), восточной (е) и западной (w) границ ячейки. Значение {} задает по­зиционирование по центру ячейки

Диспетчер компоновки place гораздо проще, чем диспетчеры pack и grid. При работе с данным диспетчером разработчик определяет абсолютные либо относительные позиции и размеры окон. Такой подход может быть приемле­мым в некоторых частных случаях, но если вам необходимо размещать боль­шое число элементов в разных окнах, диспетчер компоновки place подхо­дит плохо. Относительное позиционирование, поддерживаемое диспетчером place, удобно для создания специальных диспетчеров компоновки. Чаще все­го place применяется для формирования границы между двумя соприкаса­ющимися окнами и управления ею.

Общие сведения о диспетчере компоновки pack.Команда place позволяет задавать ширину и высоту окна, а также фик­сировать его по горизонтали и по вертикали. Размеры и расположение могут задаваться как в абсолютных, так и в относительных единицах. Относитель­ное позиционирование считается более удобным для создания интерфейсов. В примере 3.25 команда place используется для размещения окна по цен­тру его родительского окна. Подобное выражение может использоваться для отображения диалоговых окон.

Пример 3.25

place $w —in $parent  —relx 0.5 —rely 0.5 —anchor center

С помощью опций —relx и —rely компонент $w фиксируется в окне $parent. Относительное значение X (или Y), равное нулю, соответствует вы­равниванию компонента по левому (или верхнему) краю окна $parent. Зна­чение, равное единице, определяет выравнивание по правому (или нижнему) краю $parent. И, наконец, значение 0,5 задает выравнивание по центру. Оп­ция —anchor определяет, относительно какой позиции окна $w должна быть выполнена фиксация. В примере 3.25 указана точка фиксации center; в ре­зультате приведенное выше выражение приводит к выравниванию центра ок­на $w по центру окна $parent.

Относительная высота и ширина используются для того, чтобы вычис­лять размеры одного компонента, исходя из размеров другого. В примере 3.26 окно полностью закрывает родительское окно. В данном случае ис­пользуется точка фиксации по умолчанию, находящаяся в верхнем левом уг­лу окна (nw).

Пример 3.26

place $w -in $parent  -relwidth 1  -relheight  1  -x 0  -у 0

Абсолютные размеры окна и размеры, вычисленные относительно другого окна, складываются (например, в одной команде ширина может быть задана в результате суммарного действия опций —width и —relwidth). Используя обе опции, вы можете сделать ваше окно несколько меньше или несколько больше родительского. В листинге 3.27 отрицательные значения —width и —height заданы для того, чтобы уменьшить размеры окна $w относительно $parent.

Листинг 3.27.

place $w -in $parent  -relwidth  1  -relheight  1  -x 0 -у 0  -width -4 -height  -4

Окно $parent не обязательно должно быть родительским по отношению к $w. Оно может быть потомком родительского окна или окном верхнего уровня. Необходимо лишь, чтобы $w было доступным тогда, когда доступно окно $parent. Аналогичные правила действуют при использовании диспет­чера компоновки pack.

Кроме того, нет необходимости размещать компонент внутри другого ком­понента. В примере 3.28 окно $w располагается на пять пикселей выше окна $sibling. Если позиция $sibling изменится, окно $w переместится вместе с ним. Данный подход применим тогда, когда необходимо разместить в уг­лах окна с изменяемыми размерами другие компоненты. При увеличении или уменьшении окна эти компоненты автоматически изменяют свои позиции на экране.

Пример 3.28

place $w -in $sibling -relx 0.5  -у -5  -anchor s  -bordermode outside

Опция —bordermode outside указывает на то, что при позиционировании $w обрамление $sibling игнорируется. В этом случае позиция вычисляется относительно внешней границы $sibling. По умолчанию обрамление учиты­вается, что упрощает размещение окна в родительском окне.

Родительский компонент не обязательно должен быть фреймом. В ли­стинге 27.1 предпринимается попытка поместить диалоговое окно в центре текстового компонента. В примере 3.28 и $sibling, и $w могут представлять собой текстовые метки.

Управление панелями. Поддержка относительного размера и расположения делает команду place пригодной для создания новых диспетчеров компоновки. В примере 3.29 показан код диспетчера компоновки, ориентированного на управление панелями. В данном примере два фрейма, или панели, располагаются в тре­тьем фрейме. Третий фрейм играет роль контейнера, который вмещает две панели и управляет границей между ними.

В Тк 8.4 был реализован компонент panedwindow, с помощью которого можно управлять произвольным числом горизонтальных или вертикальных панелей.

Пример 3.29

proc Pane_Create {fl f2 args} {

# Отображение необязательных параметров в элементы массива

set t(-orient) vertical

set t(-percent) 0.5

set t(-in)   [winfo parent $fl]

array set t $args

#Связывание элемента массива с родительским фреймом

set master $t(-in)

upvar #0 Pane$master pane array set pane [array get t]

  • Формирование маркера и установка атрибутов, которые не должны изменяться. Для формирования тонкой разделительной линии размеры фреймов по соответствующей координате устанавливаются на один пиксель меньше, чем необходимо, а для главного окна задается черный цвет.

set pane(l) $fl

 set pane(2) $f2

 set pane(grip) [frame $master.grip -background gray50 -width 10 -height 10 -bd 1 -relief \

raised -cursor crosshair]

 if {[string match vert* $pane(-orient)]} {      

set pane(D) Y;# Adjust boundary in Y direction

place $pane(l) -in $master -x 0 -rely 0.0 -anchor nw  -relwidth 1.0 -height -1

place $pane(2) -in $master -x 0 -rely 1.0 -anchor sw  -relwidth 1.0 -height -1

place $pane(grip) -in $master -anchor с -relx 0.8

 } else {

set pane(D) X~;# Adjust boundary in X direction

place $pane(l) -in $master -relx 0.0 -y 0 -anchor nw  -relheight 1.0 -width -1

place $pane(2) -in $master -relx 1.0 -y 0 -anchor ne  -relheight 1.0 -width -1

place $pane(grip) -in $master -anchor с -rely 0.8 }

$master configure -background black

  • Установка связываний для изменения размеров,
  • для перетаскивания маркера и связывания <Configure>.

bind $master <Configure> [list PaneGeometry $master]

bind $pane(grip) <ButtonPress-l> [list PaneDrag $master %$pane(D)]

bind $pane(grip) <B1-Motion> [list PaneDrag $master $pane(D)]

bind $pane(grip) <ButtonRelease-l>[list PaneStop $master]

 # Создание исходной компоновки

PaneGeometry $master

Разбор параметров и поддержка состояния. При вызове процедуре Pane_Create передаются два компонента и произ­вольный набор параметров. Обращение к данной процедуре осуществляется следующим образом:

Pane_Create fl f2 ?-orient xy? ?-percent значение? ?-in окно?

Все необязательные параметры доступны через $args. Структура атри­бут-значение этих параметров используется для инициализации временно­го массива t. Перед обработкой $args устанавливаются значения атрибутов по умолчанию. Заполнение массива t значениями опций демонстрирует сле­дующий фрагмент кода. Размеры его невелики, но в нем не предусмотрена обработка ошибок:

set t (-orient)  vertical

set t(-percent)   0.5

 set t(-in)   [winfo parent $fl]

array set t $args

Информация о состоянии содержится в массиве, имя которого ассоции­руется с основным фреймом. Имя основного фрейма неизвестно до тех пор, пока не будет выполнен разбор параметров, поэтому используется t. После выполнения команды upvar значения параметров копируются из временного массива в глобальный массив, предназначенный для хранения данных о со­стоянии.

set master $t(-in)

upvar #0 Pane$master pane

array set pane   [array get t]

Выравнивание фреймов. В примере 3.29 при создании фреймов задается ряд параметров. Эти па­раметры запоминаются, и остальные характеристики фреймов согласуются с ними, чтобы сформировать границу между фреймами. Подобным образом параметры настройки поддерживаются во всех диспетчерах компоновки Тк. Первоначально размещение по вертикали задается следующим образом:

place $pane(l)   —in $parent  —x 0 —rely 0.0 —anchor nw —relwidth 1.0 —height -1

 place $pane(2)   -in $parent  -x 0 -rely 1.0 -anchor sw -relwidth 1.0 -height -1

place $pane(grip)   -in $parent -anchor с -relx 0.8

Расположение верхнего и нижнего фреймов задается путем указания аб­солютных значений X и относительных значений Y; точка фиксации выбира­ется так, чтобы каждый фрейм был видимым в главном фрейме. Например, нижний фрейм располагается в левом нижнем углу контейнера; на это указы­вают опции —х 0 и —rely 1.0. Опция —anchor sw фиксирует в этой позиции левый нижний угол фрейма.

Размеры вложенных фреймов также задаются как сочетание абсолютных и относительных значений. Ширина фрейма указывается равной ширине кон­тейнера с помощью опции —relwidth 1.0. Опция —height -1 уменьшает вы­соту фрейма на единицу. Значение -1 складывается с относительной высотой фрейма. В результате между фреймами, содержащимися в основном окне, остается небольшой зазор.

Маркер, используемый для изменения размеров, представляет собой не­большой фрейм, расположенный на границе между вложенными фреймами. Первоначально маркер располагается ближе к одной из границ окна (опция —relx 0.8). Впоследствии он помещается на границу между фреймами с по­мощью опции —rely. Для того чтобы пользователь мог определить момент активизации маркера, с ним связывается курсор специальной формы.

Связывание событий. В данном примере осуществляется связывание событий. В частности, со­бытие <Configure> возникает тогда, когда пользователь изменяет размеры главного окна. Когда пользователь помещает курсор мыши на маркер, нажи­мает кнопку мыши и перетаскивает границу между фреймами, то в резуль­тате его действий последовательно генерируются событие <ButtonPress-l>. одно или несколько событий <B1-Motion> и, наконец, событие <ButtonRelease-l>. В данном примере для связывания событий вызываются следующиеTcl-команды:       .

bind $parent <Configure>   [list PaneGeometry $parent]

bind $pane(grip)  <ButtonPress-l> [list PaneDrag $parent %$pane(D)] bind $pane(grip)  <B1-Motion> [list PaneDrag $parent %0$pane(D)]

bind $pane(grip)  <ButtonRelease-l>   [list PaneStop $parent]

Управление размещением фреймов. Код данного примера составлен так, что с его помощью можно поддер­живать как горизонтальное, так и вертикальное расположение. Переменная pane(D) может иметь либо значение X (горизонтальное расположение), ли­бо значение Y (вертикальное расположение). Это значение используется при обработке событий для получения %Х или %Y. При возникновении событий %Х или %,Y замещаются значениями позиции курсора мыши X и Y. Данное зна­чение передается процедуре PaneDrag как параметр D. Процедура PaneDrag запоминает предыдущую позицию в pane (lastD) и использует ее для обнов­ления границы между вложенными панелями.

Пример 3.30.

proc PaneDrag {master }

 upvar #0 Pane$master pane

 if   [info exists pane(lastD)]   {

set delta   [expr double($pane(lastD)   — $D)   $pane(size)]

set pane(-percent)   [expr $pane(-percent)   — $delta]

if  {$pane(-percent)   < 0.0} {

set pane(-percent)  0.0

 }elseif  {$pane(-percent)   > 1.0} {

set pane(-percent)   1.0}

PaneGeometry $master }

set pane(lastD) $D}      

proc PaneStop {master} {

upvar #0 Pane$master pane

catch {unset pane(lastD)}

Процедура PaneGeometry устанавливает позиции фреймов. Она вызыва­ется при изменении размеров главного окна, поэтому при ее выполнении об­новляется pane (size). Она также вызывается при перетаскивании маркера. Размеры двух вложенных фреймов определяются путем установки относи­тельного значения высоты. Как вы помните, относительные значения высоты используются совместно с абсолютным значением, равным —1, в результате чего между фреймами сохраняется небольшой зазор.

Пример 3.31.

proc PaneGeometry {master} {

upvar #0 Pane$master pane

if {$pane(D) == «X»} {

place $pane(l) -relwidth $pane(-percent)

place $pane(2) -relwidth [expr 1.0 — $pane(-percent)]

place $pane(grip) -relx $pane(-percent)

set pane(size) [winfo width $master]

} else {

place $pane(l) -relheight $pane(-percent)

place $pane(2) -relheight [expr 1.0 — $pane(-percent)]

place $pane(grip) -rely $pane(-percent)

set pane(size) [winfo height $master]}}

proc PaneTest {{p   .p} {orient vert}} {

 catch {destroy $p}

frame  $p  -width 200  -height  200

label $p.l  -bg blue -text foo

label $p.2 -bg green -text bar

 pack $p -expand true -fill both

pack propagate $p off

Pane_Create $p.l $p.2  -in $p  -orient $orient  -percent  0.3

 

 

Таблица 3.5. Команда place

  place окно ?окно ..? ?опции? Выполняется аналогично place configure
  place configure окно ?окно ..? ?опции? Размещает один или несколько компонентов, учиты­вая заданные значения опций.
  place forget окно ?окно …? Удаляет указанные окна из стека
place info окно Возвращает параметры, определяющие размещение указанного окна  
place slaves окно Возвращает список компонентов, содержащихся в указанном окне  

В таблице 3.6 перечислены опции, устанавливаемые командой place configure. Сведения о текущих установках можно получить, вызвав команду place info.

Таблица 3.6. Опции, определяющие особенности размещения компонентов

-in окно Размещение внутри или относительно указанного окна
—anchor  тил_фиксации Значения опции, или якоря: center, n, ne, e, se, s, sw, w или nw. По умолчанию принимается значение nw
—х координата Позиция   точки   фиксации   по   горизонтали.    Задается в экранных единицах измерения
—relx смещение Относительная позиция по горизонтали: 0.0 — левая гра­ница, 1.0 — правая граница
—у координата Позиция точки фиксации по вертикали. Задается в экран­ных единицах измерения
—rely смещение Относительная позиция по вертикали: 0.0 — верхняя гра­ница, 1.0 — нижняя граница
—width размер Ширина окна в экранных единицах измерения
—relwidth размер Ширина окна. Вычисляется относительно ширины роди­тельского окна. Если указано значение 1.0, окна имеют одинаковую ширину
—height размер Высота окна в экранных единицах измерения
—relheight размер Высота окна. Вычисляется относительно высоты родитель­ского окна. Если указано значение 1.0, окна имеют одина­ковую высоту
—bordermode режим Если задан режим inside, то размер и позиция вычис­ляются относительно части родительского окна, лежащей в обрамлении. Режим outside указывает на то, что раз­мер и позиция вычисляются относительно внешней грани­цы родительского окна. По умолчанию принимается зна­чение inside

 

 

 

Загрузка...