Современные
визуальные среды разработки, как правило, позволяют
легко сконструировать интерфейс вашей программы из
готовых стандартных элементов. Визуально же могут быть
настроены и многие свойства этих элементов. Не является
исключением и Флэш МХ. Такие элементы интерфейса
называются во Флэш
компонентами. Вы сможете не только использовать
готовые компоненты, но и
делать собственные и, более того, самостоятельно писать
интерфейсы настройки, которые будут функционировать
прямо в среде разработки Флэш МХ. Но обо всем по порядку.
Сначала обсудим, какие готовые
компоненты нам предоставляет Флэш.
Готовые компоненты
интерфейса
По сравнению
с Flash 5, во Flash MX появилась новая панелька -
Components. На ней есть почти все, может
понадобиться при построении пользовательского интерфейса.
Список готовых
компонентов
- Кнопка
- Радиокнопка
- Чекбокс
- Листбокс
- Комбо-бокс (выпадающий
список)
- Линейка прокрутки
- Панель прокрутки
Общие правила
пользования
Пользоваться компонентами
нужно примерно так же, как и символами библиотеки:
перетаскиваем на сцену, даем имя, настраиваем те же
свойства, что есть у всех клипов в закладке свойства
панели Properties.
Но вы уже
заметили, что у всех компонентов
на панели Properties появляется еще одна закладка
- Parameters. Именно с помощью этих
параметров можно очень
быстро адаптировать компонент,
разработанный Macromedia, для конкретного флэш-ролика.
Здесь есть все, или почти все, что нужно. Например, для
кнопки вы можете настроить текст заголовка и функцию
реакции, для чекбокса (кроме тех же
параметров) - начальное
значение и размещение текста относительно собственно
чекбокса.
Что
происходит, когда мы перетаскиваем
компонент с панели Components на сцену?
Заметили вы это уже или нет, но в библиотеку ролика за
ним попадает много символов - собственно символ
компонента и все символы,
из которых он состоит.
После того,
как все это попадет в библиотеку, вы фактически
работаете с символами из библиотеки. Например, если
изменить файлы в специальном каталоге с
компонентами (после
перетаскивания компонента
на сцену), для этого ролика уже ничего не изменится. Так
что, в том, что компоненты
лежат в панельке Components, еще ничего
замечательного нет, в этом смысле они мало чем
отличаются от, например, Common Libraries (Window
/ Common Libraries), да и просто от символов
библиотеки. Просто они попадают в библиотеку ролика из
специального места.
Чем же
все-таки отличаются компоненты
от обычных клипов?
Во-первых,
как вы уже заметили, у них есть
параметры, а во-вторых, они реагируют на
изменение этих параметров
во время редактирования ролика (live
preview, см. далее в этой лекции), и эти два
фактора делают их намного более мощными инструментами
для быстрой разработки приложений, чем просто клипы.
Настройка внешнего
вида компонентов
Поговорим о
том, как можно настраивать внешний вид готовых
компонентов Flash МХ.
Итак, что
же поддается настройке? Во-первых, параметры текста,
во-вторых - цвета скинов
компонента (на уровне их элементов), в третьих -
сами скины.
Настройка параметров
текста и цветов скинов
Во Flash MX
есть независимый от типов
компонентов набор свойств (в неоднозначных
случаях будем их также называть свойствами скинов), вся
совокупность которых полностью формирует цвет скина и
параметры текста
компонентов. (Здесь надо
иметь в виду, что эти свойства не являются свойствами
классов компонентов; все
они записаны в специальном объекте - или нескольких
объектах - типа FStyleFormat.)
Например, свойство "face"
определяет цвет заливки основной части
компонентов, свойство "background"
- цвет подложки контрола, а
свойство "textBold" -
нужно ли использовать жирный шрифт в качестве основного
шрифта для компонентов.
Полный список свойств вы найдете в online-документации в
описании свойств объекта
FStyleFormat. Замечательное удобство состоит в
том, что эти свойства можно изменить всем
компонентам одновременно (можно,
правда, сделать это и выборочно). Подчеркнем еще раз,
что рассматриваемые свойства не зависят от типа
компонента, они р аботают
для всех компонентов Flash
MX. Такая концепция позволяет довольно легко настроить
цвет скина и параметры текста для него, не задумываясь
над тем, какие именно компоненты
используются в вашем ролике, а какие - нет. Сейчас мы
опишем подробно, каким образом эти возможности
реализованы и как правильно ими пользоваться.
Сначала
рассмотрим настройку цвета. Визуальное представление
компонента образовано
множеством мелких элементов, которые в зависимости от
текущих параметров компонента
(в частности, его размеров, формы и текущего состояния)
тем или иным образом размещаются на экране,
растягиваются, меняют прозрачность и т.д. Все эти мелкие
элементы мы будем называть элементами скина. Это
название хорошо тем, что оно акцентирует внимание на
важном факте: скин может быть перекрашен или вовсе
изменен, хотя сам компонент
останется тем же самым. Итак, чтобы поддерживать
централизованное перекрашивание, каждый элемент скина
регистрируется специальным образом (в стандартных
компонентах это, разумеется,
уже сделано). При регистрации указывается, на изменение
какого именно свойства будет реагировать данный элемент.
Регистрация производится с помощью вызова
registerSkinElement в
символах, группирующих элементы скинов. Объясним
подробнее, что это за специальные символы.
Группирующие символы - это символы, которые объединяют в
себе несколько элементов скинов по некоему признаку,
чаще по состоянию компонента
- скажем, кнопка нажата, отключена (disabled) и
пр. В самом компоненте уже
лежат не элементы скинов, а группирующие символы.
Например, в
группирующем символе
fsb_downArrow (он лежит в библиотеке в папке
Flash UI Components / Component Skins / FScrollBar skins
- только вытащите на сцену
компонент ScrollBar
или любой другой, его использующий, а не то этих папок в
библиотеке не будет) вы увидите такой код:
var component =
_parent _parent;
//...
component.registerSkinElement(arrow_mc, "arrow");
component.registerSkinElement(face_mc, "face");
component.registerSkinElement(shadow_mc, "shadow");
component.registerSkinElement(darkshadow_mc, "darkshadow");
component.registerSkinElement(highlight_mc,
"highlight");
component.registerSkinElement(highlight3D_mc,
"highlight3D");
Таким
образом, например, экземпляр клипа
fsb_downArrow_arrow,
лежащий в группирующем символе
fsb_downArrow и называющийся
arrow_mc, регистрируется в
содержащем его компоненте
для реакции на свойство скина "arrow".
Отметим, что механизм регистрации элементов скина
требует, чтобы сам компонент
был унаследован от базового класса стандартных
компонентов Flash MX -
FUIComponent.
Итак,
регистрации элементов скина вполне достаточно, чтобы они
реагировали на попытки изменить их цвет (что можно
сделать несколькими способами, о чем мы расскажем далее).
А что нужно для того, чтобы текст внутри
компонентов реагировал на
сигналы об изменении его формата? Здесь кроме
наследования компонента от
FUIComponent нужно, чтобы
текст выводился при помощи стандартного блока,
являющегося составной частью всех стандартных
компонентов, содержащих в
себе текст. Этот блок называется
FLabel. Когда компонент
(наследник FUIComponent)
оповещают об изменении некоторого свойства формата (это
всегда заканчивается вызовом метода
setStyleProperty, о
котором далее), он первым делом проверяет, не начинается
ли имя свойства со слова text.
Если да - он (внутри метода
setStyleProperty) отбрасывает от имени свойства
этот начальный фрагмент и получается имя свойства
объекта TextFormat (легко
проверить, что между свойствами объектов
FStyleFormat и
TextFormat имеется такое
соответствие). В результате метод
setStyleProperty имеет возможность сформировать
объект TextFormat, который
затем будет применен к текстовому полю внутри
FLabel. Если же имя
свойства не начинается со слова
text, то делается вывод, что передается
информация о цвете элементов скина, зарегистрированных
на это свойство.
Мы с вами
рассмотрели, какие действия предпринимаются внутри
компонента для того, чтобы
он воспринимал сигналы об изменении формата. Подчеркнем,
что вам это все нужно будет проделывать только в том
случае, если вы пишете собственный
компонент. А стандартные
компоненты Flash MX уже готовы реагировать на
ваши воздействия.
Перечислим
теперь три различных (хотя и родственных) способа
воздействия на формат скина.
Способ
1. Использование setStyleProperty.
У каждого
компонента есть метод
setStyleProperty (этот
метод определен в базовом классе всех
компонентов Flash MX -
FUIComponent). Синтаксис
метода следующий:
setStyleProperty
(property, value);
Например:
myComboBox1.setStyleProperty
("face", "0xFF0000");
Способ
2. Использование собственных объектов FStyleFormat.
Во Flash MX
есть класс FStyleFormat,
назначение объектов которого - переопределять некоторые
свойства скинов. Затем вы можете подписать на сообщения
об изменении объекта класса
FStyleFormat какие-то
компоненты, которые будут реагировать на
изменения свойств скинов в этих объектах.
Подписаться
можно так:
fstyleFormatObject.addListener (someComponent);
А отменить
подписку - так:
fstyleFormatObject.removeListener (someComponent);
Для того
чтобы изменения свойства в объекте
FStyleFormat отразились на
всех подписанных компонентах,
нужно вызывать applyChanges,
которой передается либо имя свойства скина, которое
нужно обновить, либо ничего, тогда обновляются все
свойства:
fstyleFormatObject.applyChanges(propertyName)
или
fstyleFormatObject.applyChanges();
Пример.
fs = new
FStyleFormat(); // создаем объект FStyleFormat
fs.addListener (cmb2); // подписываем на этот
объект существующий
// комбобокс с
именем cmb2
fs.face = 0xFF0000; //меняем цвет основной части
компонента
fs.applyChanges(); //инициируем изменение
Способ
3. Использование globalStyleFormat.
Во Flash MX
существует предопределенный объект класса
FStyleFormat, на который
по умолчанию подписаны все
компоненты (но от него можно отписаться).
Пример.
globalStyleFormat.removeListener(cmb1);
globalStyleFormat.face = 0x00FF00;
globalStyleFormat.textBold = true;
globalStyleFormat.applyChanges();
Как мы уже
говорили, даже в последних двух случаях (когда
компонент подписан на
сообщения об изменении формата) после вызова
applyChanges у
компонентов все равно в
конце концов вызываются именно методы
setStyleProperty для
соответствующих свойств.
Если вы
хотите узнать больше о методе
setStyleProperty и о классе
FStyleFormat, вы можете
посмотреть код, описывающий их (и ряд родственных им
вещей) в клипе FUIComponent
(вам нужен фрагмент начиная со строки 196 и до самого
конца кода в первом кадре). Найти этот клип можно так:
если вы вытащили на сцену хотя бы один
компонент из панели
Components, то в вашей библиотеке есть папка
Flash UI Components. Внутри нее открываем папку
Core Assets - Developer Only, а в ней - папку FUI
Component Class Tree. В ней и лежит
компонент
FUIComponent,
обеспечивающий базовую функциональность всех стандартных
компонентов Flash MX.
Настройка скинов
А что, если
мы хотим изменить не только цвет, но и сам внешний вид
скинов?
Для этого
нужно изменить содержимое символа, группирующего
элементы скинов. Например, если вы хотите изменить вид
галочки у комбо-бокса во вжатом состоянии, вам нужно
повлиять на содержимое символа
fsb_downArrow_press, который лежит в папке
Flash UI Components / Component Skins / FScrollBar skins.
Это можно
сделать двумя способами.
- Во-первых,
аккуратно подправить сами элементы скинов. Метод
практически без побочных эффектов.
- Во-вторых,
"выбросить" старые элементы скинов и просто
нарисовать в этом символе все, что вам нравится.
Например, для
fsb_downArrow_press это пройдет совершенно
безболезненно (потому что элементы из
fsb_downArrow не
размещаются программно). Но обратите внимание, если
ваши новые элементы будут иметь не такие имена, как
старые, то цветами этих новых элементов больше
нельзя будет управлять с помощью свойств скинов. Из
этой ситуации есть два выхода: либо назвать их
также, либо переписать вызовы
registerSkinElement в первом кадре слоя
README группирующего символа (например,
fsb_downArrow_press).
Возможные проблемы при
создании собственных скинов
Просто
заменить группирующие символы или элементы скинов не
всегда бывает достаточно. Допустим, вам нужно создать
сложный скин, который состоит из большего числа
элементов, чем стандартный скин, или же ваш скин должен
сильно отличаться по форме от стандартных. В таком
случае вы заметите, что все работает не так как нужно.
Это потому, что стандартные алгоритмы размещения
элементов скинов, которые находятся в методах классов
стандартных компонентов,
зачастую учитывают размеры или другие характеристики
стандартных элементов скинов.
В подобной
ситуации вам придется переопределять те или иные методы
классов стандартных компонентов.
Мы советуем просмотреть для этого лекции, посвященные
разным видам наследования, чтобы переопределить нужные
методы наилучшим способом.
Поддержка нескольких
скинов
Представьте, что вы хотите написать библиотеку скинов
для стандартных компонентов
и использовать ее во многих флэш-роликах. Что можно
сделать, чтобы не нужно было поддерживать каждый
флэш-ролик отдельно? Очевидно, скины нужно держать
где-то отдельно от компонентов
и иметь способ их подменять. Определим сначала, что
именно мы будем подменять (группирующие символы или
непосредственно элементы скинов). Второе является более
дальновидным решением, ибо:
- загружать
потребуется меньшее количество элементов;
- обеспечивается
большая гибкость (можно в разных скинах делать
разную разбивку на элементы, если это нужно).
Хорошо, а
с помощью какого механизма мы будем подменять скины во
флэш-роликах? Во Flash MX имеется два механизма,
позволяющих сделать это во время исполнения (runtime
sharing и loadMovie,
см. лекции 13 и 14 соответственно) и один - во время
компиляции (author time sharing, см. также лекцию
13). Сейчас мы поясним в двух словах, что означает
название каждого из механизмов, а подробные разъяснения
отложим до соответствующих лекций. Итак, при runtime
sharing клип подгружается во время выполнения, при
этом путь, откуда берется этот клип, задается в процессе
редактирования ролика. Написания программного кода этот
способ не требует. Напротив,
loadMovie обеспечивает программную загрузку клипа
во время выполнения. Наконец, author time sharing
(название не является общепринятым) подгружает клип из
другого *.fla-файла во время компиляции.
В нашем
случае мы будем рассматривать лишь runtime-sharing
и author time sharing. Что касается
loadMovie, то этим
методом, скорее всего, воспользоваться не удастся,
потому что структура стандартных
компонентов Flash MX этого не предусматривает.
Теоретически, конечно, можно установить всем
нарисованным элементам компонента
режим полной прозрачности, а затем при помощи
attachMovie загрузить
внутрь группирующего символа нужные элементы (ролик с
которыми был, в свою очередь, подгружен во время
выполнения при помощи loadMovie).
Практически же это сопряжено со множеством неудобств,
вызванных с тем, что компонент
ничего не знает про новые элементы, а желает работать со
старыми (мы ведь считаем, что вы модифицируете готовый
компонент, а не пишете
свой). Поэтому далее мы не будем обсуждать использование
loadMovie для нашей цели.
А вот варианты с author time sharing и runtime sharing
мы сейчас рассмотрим подробнее.
-
Runtime sharing.
Для
каждого группирующего символа настроим runtime
sharing из *.swf-файла с группирующими символами.
Группирующий символ вместе со всеми элементами
скинов будет подменяться флэш-плеером во время
выполнения. Прочтите также лекцию 13, чтобы узнать,
как это делается, а также получить представление о
возможных проблемах с runtime sharing.
-
Author time sharing.
Для
каждого группирующего символа настроим author time
sharing из *.fla-файла, в котором хранятся
группирующие символы (см. лекцию 13). Тогда при
каждой перекомпиляции содержимое группирующего
символа будет заменяться на нужное (вместе со всеми
необходимыми элементами).
В
последнем случае вас может поджидать одна неприятность.
Допустим, что вы хотите использовать несколько разных
скинов не со стандартными
компонентами Flash MX, а со своей библиотекой
компонентов. В этом случае
полезно настроить author time sharing
компонентов из своей
библиотеки целиком, чтобы
компоненты всякий раз обновлялись у разработчиков
при внесении в них изменений (см. лекцию 13). К
сожалению, когда вы добавите "второй уровень" author
time sharing (для подгрузки правильных скинов),
Flash MX перестанет нормально компилировать ваши
флэш-ролики, а будет "вываливаться" каждый раз с ошибкой
"Pure virtual function call". Если вам зачем-то очень
нужно использовать именно такой способ работы, то из
этой ситуации есть хакерский выход: нужно отключить
author time sharing либо для всего
компонента, либо для
группирующего символа во флэш-ролике, после чего
скомпилировать его, затем можно будет опять включить
author time sharing. Но, в целом, мы не рекомендуем
такой способ работы (использование "двухровневого"
author time sharing). Если же группирующий символ
обновляется при помощи runtime sharing, то
вышеописанной проблемы не возникнет (хотя возникнет ряд
других - но вполне решаемых - проблем; см. лекцию 13).
Так что
если вы на основе встроенных
компонентов Flash MX пишете свою библиотеку,
которой будет пользоваться несколько разработчиков (и в
которую вы, скорее всего, захотите время от времени
вносить исправления), рекомендуем обновлять группирующий
символ при помощи runtime sharing.
Еще немного о
внутреннем устройстве компонентов
Итак, вы
уже кое-что знаете об устройстве стандартных
компонентов Flash MX, в
том, что касается скинов.
Остановимся отдельно еще на некоторых характерных
деталях их реализации, знание этих деталей может быть
полезным при модификации этих
компонентов для создания собственных библиотек.
Базовый класс -
FUIComponent
Все
стандартные компоненты
Flash MX наследуются от базового класса
FUIComponent, который
лежит в папке Flash UI Components / Core Assets -
Developer Only / FUIComponent Class Tree.
В классе
FUIComponent, например:
- определяется
стандартная реализация некоторых важных методов,
таких, как getEnabled,
setEnabled,
setStyleProperty
(работа со стилями), setSize,
invalidate,
drawRect (базовые
методы по отрисовке
компонентов и фокуса);
- закладывается вся
реализация по работе с клавиатурным фокусом;
- определяется
метод registerSkinElement,
обсуждавшийся выше;
- определяется
класс FStyleFormat,
обсуждавшийся выше.
FLabel
FLabel -
это "текстовая" часть всех стандартных
компонентов Flash MX. Найти
этот символ можно в папке Flash UI Components /
Component Skins / Global Skins.
В
большинстве конструкторов стандартных
компонентов можно найти
такой вызов:
this.attachMovie("FLabelSymbol","fLabel_mc",2);
После чего
вся работа с текстом осуществляется через поле
fLabel_mc.
Например,
в методе setLabel класса
FPushButtonClass,
реализующего кнопку, вы увидите такой вызов:
this.fLabel_mc.setLabel(label);
Пишем собственный
компонент
Что вообще
означает словосочетание "собственный
компонент"? Ведь в слова
"стандартный компонент" мы
вкладывали сразу несколько вещей: это
элемент управления (контрол),
он доступен из панели Components, он является
наследником FUIComponent.
Но, оказывается, все это - не основные признаки
компонентов, и у ваших
компонентов их может не
быть (и многих, скорее всего, не будет). Важно другое:
то, что компоненты - это
клипы, которые имеют настраиваемые
параметры, причем эти
параметры могут настраиваться из закладки
Parameters панели Properties прямо в процессе
редактирования *.fla-файла.
В качестве
учебного примера давайте создадим прямоугольник,
которому можно скруглять углы.
Как объявить компонент
Что же
нужно сделать, чтобы превратить наш клип-класс в
компонент?
Достаточно
задать хотя бы один параметр,
указать custom user interface или
live preview (об этом см.
ниже) в пункте Component Definition контекстного
меню символа библиотеки. Заметьте, что ни
параметры, ни custom
user interface, ни live
preview не являются для символа обязательными.
После
этого пиктограмма символа изменится на пиктограмму
компонента, а при
использовании компонента на
сцене в панельке Properties появляется вторая
закладка - Parameters.
Как сконфигурировать
параметры
Рассмотрим
детальнее, как сконфигурировать
параметры, которые будут у
компонента.
Мы хотим
задать нашему компоненту
Rectangle три
параметра: длину, ширину и
радиус скругления углов. Открываем пункт Component
Definition из контекстного меню символа
Rectangle и создаем три
параметра.
Здесь
нужно указать названия параметров
(именно эти имена будут отображаться в панели
Parameters), имена полей, соответствующих
параметрам, значения по
умолчанию и тип, который нужно выбрать из выпадающего
списка. В нашем случае все три
параметра (width,
height и
roundRadius) будут типа
Number.
Если вам
понадобятся другие типы параметров,
вы всегда сможете выбрать из имеющегося многообразия (Default,
Array,
Object,
List,
String,
Number,
Boolean,
Font Name,
Color). Для всех
стандартных типов параметров
существуют удобные контролы
редактирования значения (которыми можно пользоваться,
если вы не используете custom user interface).
После того
как вы задали параметры
компоненту, они появляются
на закладке Parameters панели Properties
для любого экземпляра компонента.
Важно
понимать, что значения параметров,
заданные для каждого экзмепляра
компонента, сохраняются где-то во внутренних
структурах во .fla-файле.
Но,
разумеется, нашей целью является не просто сохранить
параметры компонента; эти
параметры еще и должны быть
доступны в runtime. И они будут там доступны - просто
как поля клипа, из которого мы сделали
компонент. Как они попадают
в клип? Оказывается, для каждого
компонента Флэш МХ генерирует дополнительный код,
который просто присваивает соответствующим полям нужные
значения (этот код можно обнаружить, запустив ролик с
компонентом под
отладчиком). В нашем случае этот код будет выглядеть
так:
onClipEvent
(initialize) {
width = 100;
height = 35;
roundRadius = 3;
}
Этот код
будет выполнен при создании экземпляра данного клипа.
Если клип зарегистрирован как объект какого-либо класса,
то к моменту вызова конструктора все уже будет готово и
параметрами компонента в
конструкторе можно пользоваться.
Но если
параметры устанавливаются
таким простым способом, обязательно ли задавать
фиксированный набор параметров
каждому экземпляру данного символа? Действительно, это
необязательно. Если в диалоге определения
компонента вы снимете
флажок "Parameters are locked in instances", то,
устанавливая параметры
каждого конкретного экземпляра, вы сможете также удалять
старые параметры или
добавлять новые.
Использование custom
user interface
Интерфейс
среды Флэш МХ, предназначенный для работы с
компонентами, достаточно
удобен, если ваши компоненты
не слишком сложны. Но иногда требуется сделать
компонент, инструменты
настройки которого были бы сильно связаны друг с другом
(например, при включенном свойстве "точная настройка"
появляются пять дополнительных
контролов и пропадают два старых). Другой пример:
вы должны указать положение точки внутри некоторой
области - разумеется, удобнее всего поместить точную или
уменьшенную копию этой области прямо в интерфейсе
настройки и попросить пользователя указать нужную точку
мышью. Именно для таких целей предназначен механизм "custom
user interface", то есть интерфейса, определяемого
пользователем.
Что представляет собой
custom user interface
Если
немного подумать, то становится понятно, что самый
простой механизм, с помощью которого можно устроить
custom user interface (далее -
CustomUI) - это написать отдельный флэш-ролик,
который, собственно и является этим
CustomUI, и обеспечить его
взаимодействие с компонентом.
Именно так
и поступили в Macromedia.
Сделаем
простой флэш-ролик с live preview,
например, что-нибудь такое:
Обмен информацией:
объект xch
Чтобы
закончить ролик, описывающий
CustomUI, нужно обеспечить передачу заполненных в
нем пользователем параметров
в компонент. Для этого во
FlashMX существует специальный встроенный объект по
имени xch
(сокращение от exchange). Создавать этот объект не
нужно, для ролика, подключенного в качестве
CustomUI он будет доступен
и так. Фактически, поля этого объекта и будут
скопированы в поля экземпляра вашего
компонента при его
инициализации (имеется в виду инициализация в runtime).
Впрочем, если хотите, вы можете создать объект
xch
явно (это может пригодиться для целей тестирования
CustomUI в режиме обычного
ролика, когда никто за нас о создании
xch
заботиться не будет). Такой дополнительный объект
xch
ничуть не помешает работе CustomUI.
Итак, вот
какой код нам нужно написать в нашем ролике с
CustomUI:
xch.width =
widthTextField.text;
xch.height = heightTextField.text;
xch.roundRadius = roundRadiusTextField.text;
Где
следует разместить этот код? Тут может быть два варианта:
- разместить в
CustomUI кнопку
Update и "повесить" этот код на кнопку. Это
самый простой способ, тогда не нужно отслеживать
изменения значений в полях ввода. Но у этого способа
есть и недостаток: если пользователь не нажмет на
кнопку Update, измененные значения
параметров никогда не
попадут в поля экземпляра
компонента;
- любым способом
(например, используя обработчик
onChanged() для
текстовых полей) отследить, что пользователь изменил
значение одного из параметров,
и немедленно выполнить соответствующую строчку кода
по передаче данных в
xch. Этот способ
сложнее, и у него тоже есть недостаток: он может
привести к слишком частому обновлению
live preview (о
live preview -
дизайн-версии вашего
компонента - см. далее в этой лекции), что, в
свою очередь, приведет к снижению скорости
разработки, если live preview
сложное и обновляется достаточно долго. (Кстати,
именно по этой причине скорость обновления данных в
live preview - всего
раз в секунду.)
Давайте
теперь подключим CustomUI к
нашему компоненту.
Подключение CustomUI.
Внедренный и внешний интерфейс
Открываем
пункт Component Definition контекстного меню
символа и нажимаем на кнопку Set (которая
касается CustomUI). Теперь
у нас есть два варианта, которые более детально
обсуждаются ниже. Но в любом случае после этого нужно
будет нажать на кнопку Browse и выбрать
.swf-файл, который и будет использоваться в качестве
CustomUI.
Если
выбрать "Custom UI in external .swf file", то
CustomUI каждый раз будет
загружаться из файла, который вы укажете (этот файл
непременно должен существовать).
Если
выбрать "Custom UI with .swf file embedded in .fla
file", то Флэш встроит указанный вами *.swf-файл
внутрь *.fla-файла. Для того чтобы потом обновить его
после изменений, нажмите на кнопку Update.
Последний вариант является более удачным в том смысле,
что не нужно "таскать за собой" еще один *.swf-файл.
Например, если компонент,
для которого настроен CustomUI,
обновляется во флэш-роликах из центрального "библиотечного"
ролика с помощью author time sharing, то в случае
встроенного CustomUI
последнее будет обновляться автоматически, обновлять у
всех разработчиков *.swf-файл с
CustomUI не нужно.
Правда, у
этого способа есть и недостаток. Допустим, вы хотите
реализовать сложный CustomUI,
который считывает параметры
по умолчанию из внешнего файла. Авторам не удалось
реализовать такую схему с использованием встроенного
CustomUI, потому что в его
случае Флэш как бы "теряет" контекст текущей директории
и не в состоянии корректно обратиться к внешнему файлу.
Проблема размеров
Если
количество настроек у вашего
компонента достаточно велико, то и размер
CustomUI будет большой, и
он не поместится в панельку Properties. Для таких
случаев в настройках CustomUI
компонента есть специальная
опция: Display in Property Inspector или
Display in Component Parameters Panel. Если выбрать
последний вариант, то для отображения
CustomUI будет открываться
специальное окошко.
Иногда
СustomUI в этом окне отображается не вполне
корректно, например, срезаются верхушки
контролов и т. п. К
сожалению, мы не нашли решения этой проблемы.
Сохранение информации
о состоянии контролов и параметры по умолчанию
Допустим,
вы реализовали достаточно сложный
компонент с большим количеством настроек и
используете много этих компонентов
в каждом флэш-ролике, причем каждый со своими
параметрами. Также вы
предусмотрели значения параметров
по умолчанию, которые загружаются из внешнего файла. В
таком случае вам необходимо предусмотреть проверку в
CustomUI, результатом
которой будет либо загрузка
параметров из внешнего файла (если
параметры еще никогда не
были установлены для этого
компонента), либо отображение в
CustomUI
параметров, уже один раз
установленных пользователем (эти
параметры сохраняются в конкретном
компоненте-экземпляре во
внутренних структурах .fla-файла и доступны через объект
xch).
Эта
проверка может выглядеть следующим образом:
if (!xch.alreadyRunBefore)
{
xch.alreadyRunBefore = true;
//загружаем значения параметров по умолчанию.
}
else {
//загружаем параметры из xch
}
Использование live
preview
Во Flash
MX действительно сделан большой шаг вперед в сторону RAD
- быстрой разработки приложений. У вас есть
компоненты повторного
использования, вы можете писать свои
компоненты, и, что самое
главное, эти компоненты
можно быстро и удобно настраивать. Исключительно важным
элементом во всей этой цепочке является технология
live preview, которая
позволяет разработчику конечного флэш-ролика сразу
видеть, как будет выглядеть тот или иной
компонент после запуска при
изменении только одного параметра.
Это существенно ускоряет разработку.
Технология
live preview во Flash MX
имеет много схожих черт с CustomUI:
live preview - это
отдельный *.swf-файл, который разработчик и будет видеть
на сцене на месте настраиваемого
компонента.
Две возможные
стратегии реализации live preview
Представьте себе, что у вас есть сложный
компонент, например,
визуализатор математических формул. Вы хотите наблюдать
формулу прямо во время редактирования флэш-ролика,
поэтому вы делаете live preview.
В таком случае имеет смысл положить во флэш-ролик с
live preview сам
компонент-визуализатор.
Тогда при внесении каких-либо изменений в
компонент-визуализатор, вы
просто заново перетащите его в библиотеку ролика с
live preview, и последний
будет работать в соответствии со сделанными изменениями.
Возможен
другой подход: в live preview
вы помещаете не сам компонент,
а его простую модель, которая вас устраивает в качестве
preview (например, если сам
компонент интерактивный, то модель лишена этой
интерактивности). Тогда, если вы хорошо отладите
live preview, можно вообще
о нем забыть (то, что вы будете вносить сложные
изменения в обработку интерактивности в
компоненте, не будет иметь
к live preview никакого
отношения).
Итак,
начнем делать ролик с preview. Как ни странно,
начать надо с проверки того, нарисовано ли вообще хоть
что-нибудь в самом компоненте
(не в preview). Дело в том, что, хотя вы можете
создавать пустые клипы нулевого размера (скажем, чтобы
затем нарисовать в них что-нибудь динамически во время
выполнения), подключить preview к
компоненту, в котором
ничего не нарисовано, вы можете только теоретически. То
есть, подключать - подключаете, но на экране ничего не
отображается. Поэтому (даже если вы хотите, чтобы
визуально компонент был
пуст) положите в компонент
хоть какой-нибудь графический объект (можно сделать его
полностью прозрачным).
Дальше
приступайте к рисованию preview. Вы можете
ограничиться совсем простой картинкой, дающей лишь
представление о размерах
компонента, а можете положить в ролик с
preview сам компонент с
полной функциональностью (это не всегда удается из-за
того, что компонент может
требовать присутствия специального окружения; но если
окружение не нужно, мы рекомендуем поступать именно так).
После того, как preview нарисовано, нужно
разместить в нем код, который будет отвечать за
масштабирование и выравнивание preview
относительно контрольной точки
компонента. Для решения этой задачи нам
понадобится объект Stage,
который как раз и отвечает за размещение ролика внутри
демонстрирующей его среды (например, браузера).
Параметры масштабирования можно указать при помощи поля
Stage.scaleMode. Этому
полю можно присвоить одно из четырех возможных текстовых
значений: "exactFit", "showAll",
"noBorder ", and "noScale".
По умолчанию стоит режим showAll - это значит, что ролик
масштабируется таким образом, чтобы в отводимую область
он поместился целиком. Более всего от этого режима
отличается режим noScale,
в котором масштабирование вовсе не производится.
Довольно часто именно его удобно устанавливать в
live preview. Второй важный
параметр объекта
Stage - это поле
align. Этому полю также
присваиваются текстовые значения. При этом используются
следующие соглашения: "T",
"B", "L",
"R" означают
соответственно top,
bottom,
left,
right (верх, низ, лево,
право), если стоит только одна буква, то по другой оси
подразумевается выравнивание на центр. Если же мы
равняем не по центру по обеим осям, то пишем
соответственно "TL", "TR
", "BL" или "BR".
По умолчанию используется выравнивание на центр как по
вертикали, так и по горизонтали.
Предположим, что вы нарисовали
компонент таким образом, что его опорная точка
находится в левом верхнем углу клипа. Тогда вам, скорее
всего, будет удобно нарисовать
live preview с таким же выравниванием и вызвать
внутри preview такой код:
Stage.scaleMode = "noScale";
Stage.align = "TL";
В
результате опорные точки
компонента и live preview
совпадут.
Обмен информацией:
объект xch
Обмен
информацией между компонентом
и live preview производится
примерно так же, как и между
компонентом и CustomUI.
Только теперь мы не отправляем, а получаем информацию об
измененных параметрах из
xch.
Напомним, что специально создавать этот объект не
обязательно, в контексте live
preview он будет доступен и так. Учтите также,
что информация лишь копируется из
xch интерфейса
(стандартного или CustomUI)
в xch
нашего live preview.
Поэтому вы можете без опаски изменять поля
xch
в live preview - вы ничего
не испортите и в параметры
компонента эти изменения не попадут. С другой
стороны, поля
xch для
live preview не будут
сохранены при сохранении *.fla-файла, как это происходит
с параметрами компонента.
Как в
live preview узнать, что
какие-то параметры
изменились (и нужно, скажем, изменить внешний вид)? И
для этого все предусмотрено. В любом
live preview в первом кадре
главной линейки нужно поместить функцию
onUpdate, в теле которой и
использовать новые значения
параметров:
function onUpdate() {
// достаем нужные параметры из xch
var width = xch.width;
var height = xch.height;
var roundRadius = xch.round.Radius;
// перерисовываем все, что нужно
}
Функция
onUpdate вызывается, как
только изменяется один из
параметров экземпляра
компонента (что и происходит при редактировании
параметров через
стандартный интерфейс установки
параметров или через
CustomUI).
На самом
деле то, что мы описали только что - это некоторое
приближение. В действительности же происходит следующее.
Если в объекте
xch интерфейса
("родного" или CustomUI)
происходят изменения, то устанавливается некий
внутренний флаг (или какой-то аналог флага),
сигнализирующий об этом. Раз в секунду (а вовсе не раз в
кадр, как можно было бы подумать) состояние флага
проверяется и если флаг был установлен, то содержимое
xch
из интерфейса копируется в
xch из
live preview. После этого у
live preview вызывается
функция onUpdate. Если же
флаг установлен не был, то ничего не происходит и
onUpdate не вызывается.
Подключение live
preview. Встроенное и внешнее live preview
Открываем
пункт Component Definition контекстного меню
символа и нажимаем на кнопку Set (которая
касается ive preview). И здесь у вас есть два
варианта: вы можете выбрать либо встроенное, либо
внешнее live preview, после
чего нужно нажать на кнопку Browse и выбрать
*.swf-файл, который и будет использоваться в качестве
live preview.
Все
соображения, изложенные по поводу встроенных и внешних
CustomUI, относятся и к
live preview.
У авторов
была реальная ситуация, когда
компонент загружался из runtime shared-модуля.
Перед нами стояла дилемма: можно было либо использовать
внешнее preview (тогда оно бы загружалось каждый
раз из внешнего *.swf-файла, который бы вдобавок
загружал runtime-shared модуль), либо встроить
его во *.fla-файл и отказаться от runtime sharing
в live preview (каждый раз
после изменения компонента
перетаскивать его в библиотеку
live preview, а затем убирать настройки
runtime sharing). Можно спорить о том, какой вариант
лучше, но, в любом случае, встроенное
live preview работает
намного быстрее (и это очень заметно!) Поэтому мы,
разумеется, и остановились на втором варианте.
Некоторые тонкости по
поводу расположения и масштабирования live preview
Зададим
несколько сложных вопросов.
Как себя
ведет live preview во время
масштабирования компонента
при редактировании?
Как
согласованы размеры live preview
при масштабировании компонента
с размерами этого компонента
во время выполнения?
Каких
размеров должен быть компонент
в файле с live preview?
Каких размеров должен быть этот файл?
Как
правильнее разместить компонент
относительно его registration point и как нужно
разместить этот же компонент
в файле с live preview для
адекватного масштабирования и позиционирования?
Какие
должны быть параметры у
объекта Stage файла с
live preview?
Это
вопросы действительно сложные и авторы вряд ли смогут
ответить на них однозначно. Возможно много разных
комбинаций ответов на эти вопросы (в зависимости от
того, что вы хотите получить), но мало какие из этих
комбинаций обеспечивают корректную работу.
Авторы
могут поделиться опытом по поводу одной из работающих
комбинаций, которая практически без изменений была
применена в нескольких компонентах.
Что
касается масштабирования, оно было полностью отключено:
- на уровне
live preview это
достигалось установкой
Stage.scaleMode в "noScale"
(в первом же кадре live
preview)
- на уровне самого
компонента это
достигалось путем вызова следующего кода в
конструкторе:
this._xscale = 100;
this._yscale = 100;
Авторов
устраивал такой вариант, потому что вся отрисовка
происходила полностью программно. Если же нужно было
настраивать размеры компонентов,
то применялся такой прием (опять же в конструкторе
компонента):
this.width =
this._width;
this.height = this._height;
this._xscale = 100;
this._yscale = 100;
После чего
this.width и
this.height можно
использовать как параметры для программной отрисовки.
Это хорошая альтернатива использованию явных
параметров
width и
height, значения которых
пришлось бы подбирать каждый раз.
Размер
файла с live preview в
такой конфигурации значения не имеет, собственно
live preview лежит в нем в
натуральную величину (scale = 100).
Точку
регистрации компонентов
авторы применяли как по левому краю, так и по центру (в
live preview используется
такая же, как и в основном
компоненте).
И
последнее. Как мы уже заметили, мы использовали
компоненты с исключительно
программной отрисовкой (в live
preview, разумеется, тоже). Такая конфигурация
работает только в том случае, если положить в файл c
live preview какой-то
объект (например, невидимый прямоугольник (с
alpha = 0) размером со всю
сцену). Иначе вы просто не увидите программно
отрисованной графики (будет видно только точечку на
месте компонента вместо
live preview).
Диаграмма обмена
информацией
Теперь,
когда у нас есть достаточно сведений, посмотрим на всю
картинку целиком повнимательнее. Вот как выглядит
диаграмма обмена информацией между экземпляром
компонента,
CustomUI (или стандартным
интерфейсом для задания параметров)
и live preview.
Рис. 11.1. Диаграмма обмена информацией между
экземпляром компонента, CustomUI и live preview
Что же
здесь происходит? Существует два экземпляра
компонента, каждый со
своими значениями параметров,
которые хранятся во внутренних структурах *.fla-файла (но
к этим параметрам можно
получить доступ из CustomUI
через объекты
xch, что показано
широкими стрелками).
Как только
CustomUI или стандартный
интерфейс для задания параметров
записывает значение параметра
в xch,
оно немедленно попадает в экземпляр
компонента (где и хранится
дальше), после чего немедленно изменяется значение
соответствующего параметра
в объекте
xch (обозначены звездочками), что, в свою
очередь приводит к вызову функции
onUpdate, размещенной в первом кадре
live preview.
live preview
перерисовывается, доставая все
параметры из
xch, результат чего
мы немедленно наблюдаем на экране.
|