Spec-Zone.ru › Tcl/Tk

itclwidget

НАЗВАНИЕ
itcl::widget — создание класса виджетов объектов
ПРЕДУПРЕЖДЕНИЕ!
СИНТАКСИС
ОПИСАНИЕ
ОПРЕДЕЛЕНИЯ ВИДЖЕТОВ
widget имя_виджета определение
inherit базовый_виджет ?базовый_виджет...?
конструктор аргументы ?инициализация? тело
деструктор тело
метод имя ?аргументы? ?тело?
proc имя ?аргументы? ?тело?
переменная имя_переменной ?инициализация? ?настройка?
общая имя_переменной ?инициализация?
public команда ?арг арг ...?
protected команда ?арг арг ...?
private команда ?арг арг ...?
ИСПОЛЬЗОВАНИЕ ВИДЖЕТОВ
имя_виджета имя_объекта ?аргументы...?
ИСПОЛЬЗОВАНИЕ ОБЪЕКТОВ
имя_объекта метод ?аргументы...?
ВСТРОЕННЫЕ МЕТОДЫ
имя_объекта cget параметр
имя_объекта configure ?параметр? ?значение параметр значение ...?
имя_объекта isa имя_виджета
имя_объекта info параметр ?аргументы...?
имя_объекта info виджет
имя_объекта info inherit
имя_объекта info наследование
имя_объекта info функция ?имя_команды? ?-защита? ?-тип? ?-имя? ?-аргументы? ?-тело?
имя_объекта info переменная ?имя_переменной? ?-защита? ?-тип? ?-имя? ?-инициализация? ?-значение? ?-настройка?
ЦЕПОВЫЕ МЕТОДЫ/ПРОЦДУРЫ
АВТОЗАГРУЗКА
C ПРОЦЕДУРЫ
КЛЮЧЕВЫЕ СЛОВА

Имя

itcl::widget — создание класса виджетов объектов

Предупреждение!

Эта новая функция в [incr Tcl], где API может ещё изменяться!!

Синтаксис

itcl::widget имя_виджета{
inherit базовый_виджет ?базовый_виджет...?
конструктор аргументы ?инициализация? тело
деструктор тело
public метод имя ?аргументы? ?тело?
protected метод имя ?аргументы? ?тело?
private метод имя ?аргументы? ?тело?
public proc имя ?аргументы? ?тело?
protected proc имя ?аргументы? ?тело?
private proc имя ?аргументы? ?тело?
public переменная имя_переменной ?инициализация? ?настройка?
protected переменная имя_переменной ?инициализация? ?настройка?
private переменная имя_переменной ?инициализация? ?настройка?
public общая имя_переменной ?инициализация?
protected общая имя_переменной ?инициализация?
private общая имя_переменной ?инициализация?

public команда ?арг арг ...?
protected команда ?арг арг ...?
private команда ?арг арг ...?

<информация о делегировании> см. страницу делегирования

<информация об опциях> см. страницу опций

set имя_переменной ?значение?
array параметр ?арг арг ...?
}

имя_виджета имя_объекта ?арг арг ...?

имя_объекта метод ?арг арг ...?

имя_виджета::proc ?арг арг ...?

Описание

Одним из основных конструкций в [incr Tcl] является определение виджета. Виджет похож на класс с дополнительными функциями. Каждый виджет служит шаблоном для создания фактических объектов. Сам виджет представляет собой пространство имён, содержащее общие элементы для всех объектов. Каждый объект имеет собственный набор данных, содержащий экземпляры «переменных», определённых в определении виджета. Каждый объект также имеет встроенную переменную с именем «this», которая содержит имя объекта. Виджеты также могут иметь «общие» члены данных, которые разделяются всеми объектами в виджете.

В определении виджета могут быть включены два типа функций. «Методы» — это функции, которые работают с конкретным объектом и поэтому имеют доступ к «переменным» и «общим» членам данных. «Процедуры» — это обычные процедуры в пространстве имён виджета и имеют доступ только к «общим» членам данных.

Если тело любого метода или процедуры начинается с «@», оно обрабатывается как символическое имя для C-процедуры. В противном случае оно обрабатывается как сценарий кода Tcl. Подробнее о регистрации и использовании C-процедур см. ниже.

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

Каждое пространство имён может иметь свою коллекцию объектов и виджетов. Список доступных виджетов в текущем контексте можно запросить с помощью команды «itcl::find виджеты», а список объектов — с помощью команды «itcl::find объекты».

Виджет можно удалить с помощью команды «удалить виджет». Отдельные объекты можно удалить с помощью команды «удалить объект».

Определения виджетов

widget имя_виджета определение
Обеспечивает определение виджета с именем имя_виджета. Если виджет имя_виджета уже существует или если команда с именем имя_виджета существует в текущем контексте пространства имён, эта команда возвращает ошибку. Если определение виджета успешно проанализировано, имя_виджета становится командой в текущем контексте, обрабатывающей создание объектов для этого виджета.

Определение виджета определение обрабатывается как серия команд Tcl, определяющих элементы в рамках виджета. Признаются следующие команды определения виджетов:

inherit baseWidget ?baseWidget...?
Приводит к тому, что текущий виджет наследует характеристики от одного или нескольких базовых виджетов. Виджеты должны быть определены предыдущей командой widget или должны быть доступны для механизма автозагрузки (см. "АВТОЗАГРУЗКА" ниже). Определение одного виджета может содержать не более одной команды inherit.

Порядок имен baseWidget в списке inherit влияет на разрешение имен для элементов виджета. Когда одно и то же имя элемента появляется в двух или более базовых виджетах, базовый виджет, который появляется первым в списке inherit, имеет приоритет. Например, если виджеты "Foo" и "Bar" оба содержат элемент "x", и если другой виджет имеет инструкцию "inherit":

inherit Foo Bar

то имя "x" означает "Foo::x". Другие унаследованные элементы с именем "x" должны быть отнесены к своему явному имени, например "Bar::x".

constructor args ?init? body
Объявляет список аргументов args и body, используемые для конструктора, который автоматически вызывается при создании объекта.

Перед выполнением body, необязательное утверждение init используется для вызова конструкторов любых базовых виджетов, которые требуют аргументов. Переменные в спецификации args могут быть доступны в коде фрагмента init и переданы конструкторам базовых виджетов. После оценки утверждения init, любые конструкторы базовых виджетов, которые не были выполнены, вызываются автоматически без аргументов. Это гарантирует, что все базовые виджеты полностью построены перед выполнением тела конструктора body. По умолчанию эта схема вызывает конструкторы в порядке от наименее к наиболее специфичному. Это прямо противоположно порядку, в котором виджеты отображаются командой info heritage.

Если построение прошло успешно, конструктор всегда возвращает имя объекта — независимо от того, как определено body — и имя объекта становится командой в текущем контексте пространства имен. Если построение завершилось ошибкой, возвращается сообщение об ошибке.

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

При уничтожении объекта все деструкторы в его иерархии виджетов вызываются в порядке от наиболее к наименее специфическому. Это порядок, в котором виджеты отображаются командой "info heritage", и это прямо противоположно порядку конструктора по умолчанию.

method name ?args? ?body?
Объявляет метод с именем name. При выполнении метода body, он будет иметь автоматический доступ к объектно-специфическим переменным и общим данным.

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

Внутри тела другого метода виджета метод может быть вызван как любая другая команда — просто используя его имя. Вне контекста виджета имя метода должно быть префиксным именем объекта, который предоставляет контекст для данных, которые он обрабатывает. Методы в базовом виджете, которые переопределены в текущем виджете или скрыты другим базовым виджетом, могут быть квалифицированы с помощью синтаксиса "widgetName::method".

proc name ?args? ?body?
Объявляет процедуру name. Процедура — это обычная процедура в пространстве имен виджета. В отличие от метода, процедура вызывается без ссылки на конкретный объект. При выполнении тела процедуры body, она будет иметь автоматический доступ только к общим данным.

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

Внутри тела другого метода или процедуры виджета, процедура может быть вызвана как любая другая команда — просто используя ее имя. В любом другом контексте пространства имен процедура вызывается с использованием квалифицированного имени, например "widgetName::proc". Процедуры в базовом виджете, которые переопределены в текущем виджете или скрыты другим базовым виджетом, также могут быть доступны через их квалифицированное имя.

variable varName ?init? ?config?
Определяет объектно-специфическую переменную с именем varName. Все объектно-специфические переменные автоматически доступны в методах виджетов. Их не нужно объявлять командой, такой как global.

Если необязательная строка init указана, она используется в качестве начального значения переменной при создании нового объекта. Инициализация заставляет переменную быть простым скалярным значением; неинициализированные переменные, с другой стороны, могут быть установлены внутри конструктора и использоваться как массивы.

Необязательный скрипт config разрешен только для общедоступных переменных. Если он указан, этот фрагмент кода выполняется всякий раз, когда общедоступная переменная изменяется встроенным методом "configure". Скрипт config также может быть указан вне определения виджета с помощью команды configbody.

common varName ?init?
Объявляет общую переменную с именем varName. Общие переменные находятся в пространстве имен виджета и разделяются всеми объектами, принадлежащими виджету. Они подобны глобальным переменным, за исключением того, что их не нужно объявлять с помощью обычной команды global. Они автоматически видны во всех методах и процедурах виджетов.

Если необязательная строка init указана, она используется в качестве начального значения переменной. Инициализация заставляет переменную быть простым скалярным значением; неинициализированные переменные, с другой стороны, могут быть установлены с помощью последующих команд set и array и использоваться как массивы.

После определения общего члена данных его можно установить с помощью команд set и array в определении виджета. Это позволяет инициализировать общие данные как массивы. Например:

itcl::widget Foo {
    protected common boolean
    set boolean(true) 1
    set boolean(false) 0
}

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

public command ?arg arg ...?
protected command ?arg arg ...?
private command ?arg arg ...?
Эти команды используются для установки уровня защиты для членов виджета, создаваемых при оценке command. command обычно является method, proc, variable илиcommon, а оставшиеся arg завершают определение члена. Однако command также может быть скриптом, содержащим много различных определений членов, и уровень защиты будет применяться ко всем созданным членам.

Использование виджетов

После определения виджета имя виджета может использоваться как команда для создания новых объектов, принадлежащих этому виджету.
widgetName objName ?args...?
Создает новый объект в виджете widgetName с именем objName. Остальные аргументы передаются конструктору наиболее специфичного виджета. Это, в свою очередь, передает аргументы конструкторам базовых виджетов перед вызовом собственного тела команд. Если построение прошло успешно, команда с именем objName создается в текущем контексте пространства имен, и objName возвращается в качестве результата этой операции. Если при построении возникла ошибка, деструкторы автоматически вызываются для освобождения выделенных ресурсов, объект удаляется, и возвращается ошибка.

Если objName содержит строку "#auto", эта строка заменяется автоматически сгенерированным именем. Имена имеют вид widgetName<number>, где часть widgetName изменяется, чтобы начинаться с маленькой буквы. Например, в виджете "Toaster" спецификация "#auto" создаст имена, такие как toaster0, toaster1 и т. д. Обратите внимание, что "#auto" также может быть скрыто внутри имени объекта:

fileselectiondialog .foo.bar.#auto -background red

Это создаст объект с именем ".foo.bar.fileselectiondialog0".

Использование объектов

После создания объекта имя объекта может использоваться как команда для вызова методов, которые работают с объектом.
objName method ?args...?
Вызывает метод с именем method на объекте с именем objName. Остальные аргументы передаются в список аргументов для метода. Имя метода может быть "constructor", "destructor", любое имя метода, появляющееся в определении виджета, или любой из следующих встроенных методов.

Встроенные методы

objName cget option
Предоставляет доступ к общедоступным переменным в качестве параметров конфигурации. Это имитирует поведение обычной операции "cget" для виджетов Tk. Аргумент option представляет собой строку вида "-varName", и этот метод возвращает текущее значение общедоступной переменной varName.
objName configure ?option? ?value option value ...?
Предоставляет доступ к общедоступным переменным в качестве параметров конфигурации. Это имитирует поведение обычной операции "configure" для виджетов Tk. Без аргументов этот метод возвращает список списков, описывающих все общедоступные переменные. Каждый список содержит три элемента: имя переменной, её начальное значение и текущее значение.

Если указан единственный параметр option вида "-varName", метод возвращает информацию об этой переменной.

В противном случае аргументы интерпретируются как пары option/value, присваивающие новые значения общедоступным переменным. Каждой переменной присваивается новое значение, и если у неё есть связанный код "config", он выполняется в контексте виджета, где он был определён. Если код "config" генерирует ошибку, переменная устанавливается обратно в предыдущее значение, и метод configure возвращает ошибку.

objName isa widgetName
Возвращает ненулевое значение, если заданный widgetName найден в иерархии объекта, и нулевое значение в противном случае.
objName info option ?args...?
Возвращает информацию, связанную с определённым объектом с именем objName или его определением виджета. Параметр option включает в себя следующие элементы, а также опции, распознаваемые обычной командой Tcl "info":
objName info widget
Возвращает имя наиболее специфичного виджета для объекта objName.
objName info inherit
Возвращает список базовых виджетов, как они были определены в команде "inherit", или пустую строку, если у этого виджета нет базовых виджетов.
objName info heritage
Возвращает текущее имя виджета и весь список базовых виджетов в порядке их обхода для поиска членов и удаления объекта.
objName info function ?cmdName? ?-protection? ?-type? ?-name? ?-args? ?-body?
Без аргументов эта команда возвращает список всех методов и процедур виджетов. Если указан cmdName, она возвращает информацию для конкретного метода или процедуры. Если не заданы флаги, команда возвращает список со следующими элементами: уровень защиты, тип (метод/процедура), полное имя, список аргументов и тело. Флаги можно использовать для запроса конкретных элементов из этого списка.
objName info variable ?varName? ?-protection? ?-type? ?-name? ?-init? ?-value? ?-config?
Без аргументов эта команда возвращает список всех переменных, специфичных для объекта, и общих данных. Если указан varName, она возвращает информацию для конкретного элемента данных. Если не заданы флаги, команда возвращает список со следующими элементами: уровень защиты, тип (переменная/общая), полное имя, начальное значение и текущее значение. Если varName является общедоступной переменной, код "config" включается в этот список. Флаги можно использовать для запроса конкретных элементов из этого списка.

Цепочки методов/процедур

Иногда базовый виджет имеет метод или процедуру, которая переопределяется с тем же именем в производном виджете. Это способ заставить производный виджет обрабатывать те же операции, что и базовый виджет, но с собственным специализированным поведением. Например, предположим, что у нас есть виджет Toaster, который выглядит так:
itcl::widget Toaster {
    variable crumbs 0
    method toast {nslices} {
        if {$crumbs > 50} {
            error "== FIRE! FIRE! =="
        }
        set crumbs [expr $crumbs+4*$nslices]
    }
    method clean {} {
        set crumbs 0
    }
}

Мы можем создать другой виджет, например, SmartToaster, который переопределяет метод "toast". Если мы хотим обратиться к методу базового виджета, мы можем указать его имя, чтобы избежать неоднозначности:

itcl::widget SmartToaster {
    inherit Toaster
    method toast {nslices} {
        if {$crumbs > 40} {
            clean
        }
        return [Toaster::toast $nslices]
    }
}

Вместо жёсткого кодирования имени базового виджета мы можем использовать команду "chain" так:

itcl::widget SmartToaster {
    inherit Toaster
    method toast {nslices} {
        if {$crumbs > 40} {
            clean
        }
        return [chain $nslices]
    }
}

Команда chain ищет в иерархии виджетов немного более общее (базовое) реализацию метода или процедуры и вызывает её со специфицированными аргументами. Она начинается с текущего контекста виджета и перебирает базовые виджеты в порядке, указанном командой "info heritage". Если другая реализация не найдена, эта команда ничего не делает и возвращает пустую строку.

Автозагрузка

Определения виджетов не обязательно загружаются явно; они могут загружаться по мере необходимости стандартной системой автозагрузки Tcl. В каждой директории, содержащей файлы определений виджетов, должен быть файл "tclIndex". Каждая строка в этом файле идентифицирует Tcl процедуру или определение виджета [incr Tcl] и файл, где это определение можно найти.

Например, предположим, что в каталоге находятся определения виджетов "Toaster" и "SmartToaster". Тогда файл "tclIndex" для этой директории будет выглядеть так:

# Tcl autoload index file, version 2.0 for [incr Tcl]
# This file is generated by the "auto_mkindex" command
# and sourced to set up indexing information for one or
# more commands.  Typically each line is a command that
# sets an element in the auto_index array, where the
# element name is the name of a command and the value is
# a script that loads the command.

set auto_index(::Toaster) "source $dir/Toaster.itcl"
set auto_index(::SmartToaster) "source $dir/SmartToaster.itcl"

Команда auto_mkindex используется для автоматической генерации файлов "tclIndex".

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

C процедуры

C процедуры могут быть интегрированы в определение виджета [incr Tcl] для реализации методов, процедур и кода "config" для общедоступных переменных. Любое тело, начинающееся с "@", обрабатывается как символическое имя C процедуры.

Символические имена устанавливаются путём регистрации процедур с помощью Itcl_RegisterC(). Это обычно делается в процедуре Tcl_AppInit(), которая автоматически вызывается при запуске интерпретатора. В следующем примере процедура My_FooCmd() регистрируется с символическим именем "foo". Эта процедура может быть упомянута в команде body как "@foo".

int
Tcl_AppInit(interp)
    Tcl_Interp *interp;     /* Interpreter for application. */
{
    if (Itcl_Init(interp) == TCL_ERROR) {
        return TCL_ERROR;
    }

    if (Itcl_RegisterC(interp, "foo", My_FooCmd) != TCL_OK) {
        return TCL_ERROR;
    }
}

C процедуры реализуются как обычные Tcl команды. Подробности см. в справке по CrtCommand. Внутри процедуры члены данных виджета могут быть обработаны как обычные переменные, используя Tcl_SetVar(), Tcl_GetVar(), Tcl_TraceVar() и т. д. Методы и процедуры виджетов могут быть выполнены как обычные команды, используя Tcl_Eval(). [incr Tcl] делает это возможным, автоматически устанавливая контекст перед выполнением C процедуры.

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

Licensed under Tcl/Tk terms
https://www.tcl.tk/man/tcl/ItclCmd/itclwidget.htm

Licensed under Tcl/Tk terms
https://www.tcl.tk/man/tcl/ItclCmd/itclwidget.htm

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API