Руководство по actionscript. часть 4, стр. 083
Листинг 22.14. Синхронизация двух объектов TextField
package { import flash. display.*; import flash. events.*; import flash. text.*;
public class PhotoPanel extends Sprite { private static const defaultTitle:String =
«Photo Viewer [No photo selected]«; private static const defaultPhotoName:String =
«Enter Photo Name Here»;
private var title:TextField; private var photoname:TextField;
public function PhotoPanel ( ) { // Создаем объект TextField для строки заголовка панели title = new TextField( ); title. text = PhotoPanel. defaultTitle; title. width = 350; title. height = 25; title. border = true; title. background = true; title. selectable = false; addChild(title);
// Создаем объект TextField для заголовка отдельной фотографии
photoname = new TextField( );
photoname. text = PhotoPanel. defaultPhotoName;
photoname. width =150;
photoname. height = 30;
photoname. x = 100;
photoname. у = 150;
photoname. border = true;
photoname. background = true;
photoname. type = TextFieldType. INPUT
addChild(photoname);
// Регистрируем приемник в объекте photoname // для событий Event. CHANGE
photoname. addEventLi stener(Event. CHANGE, changeLi stener);
// Регистрируем приемники в объекте photoname для событий получения // и потери фокуса
photoname. addEventLi stener(FocusEvent. F0CUS_IN. photoFocusInListener); photoname. addEventLi stener(FocusEvent. F0CUS_0UT,
photoFocusOutListener);
// Регистрируем приемник в объекте stage // для событий потери фокуса
stage. addEventListener(FocusEvent. F0CUS_0UT, panelFocusOutListener);
// Вызывается всякий раз при добавлении
// нового текста в объект photoname
private function changeListener (e:Event):void {
// Название фотографии изменилось, поэтому обновляем строку заголовка,
// чтобы ее содержимое соответствовало тексту объекта photoname
if (photoname. text. length == 0) { title. text = «Photo Viewer [Unnamed Photo]«;
} else {
title. text = «Photo Viewer [" + photoname. text + "]«;
}
}
// Вызывается всякий раз при получении фокуса объектом photoname private function photoFocusInListener (e:FocusEvent):void { // Если для фотографии еще не было указано название… if (photoname. text == PhotoPanel. defaultPhotoName) { // …очищаем поле photoname, чтобы пользователь мог ввести название photoname. text = «»;
// Обновляем строку заголовка панели, чтобы показать, что была // выбрана фотография без названия title. text = «Photo Viewer [Unnamed Photo]«; } else {
// …выбранной фотографии уже присвоено название, поэтому обновляем // строку заголовка панели, чтобы отобразить это название title. text = «Photo Viewer [" + photoname. text + "]«;
}
}
// Вызывается всякий раз, когда объект photoname теряет фокус private function photoFocusOutListener (e:FocusEvent):void { // Если пользователь не ввел название для фотографии… if (photoname. text. length == 0) { // …присваиваем названию фотографии значение по умолчанию photoname. text = PhotoPanel. defaultPhotoName;
}
}
// Вызывается всякий раз, когда фокус теряет любой объект private function panelFocusOutListener (e:FocusEvent):void { // Если на настоящий момент ни один объект не имеет фокуса… if (e. relatedObject == null) { // …присваиваем строке заголовка панели значение по умолчанию title. text = PhotoPanel. defaultTitle;
}
}
}
}
Событие Event. SCROLL
Событие Event. SCROLL возникает всякий раз, когда изменяется значение любой из следующих переменных объекта TextField: scrollH, scrollV, maxscrollH
или maxscrollV. Другими словами, событие Event. SCROLL сообщает об одном из следующих изменений в текстовом поле:
? произошла прокрутка поля по вертикали или по горизонтали (либо пользователем, либо программным путем с помощью переменных scrollH или scrollV);
? поле получило новое содержимое, которое изменяет максимальный диапазон для вертикальной или горизонтальной прокрутки;
? изменение размеров поля привело к изменению максимального диапазона для вертикальной или горизонтальной прокрутки поля.
Руководство по actionscript. часть 4, стр. 084
Обобщенный код, необходимый для регистрации приемника в объекте TextField для события Event. SCROLL, выглядит следующим образом:
объектТехЬПе Id. addEventLi stener (Event. SCROLL. scro 11L istener);
Обобщенный код для приемника события Event. SCROLL выглядит следующим образом:
private function scroll Listener (e: Event):void {
}
Обычно событие Event. SCROLL применяется для синхронизации интерфейса полосы прокрутки с содержимым поля, как показано в листинге 22.15. Полоса прокрутки в этом листинге обладает следующими возможностями:
? может применяться к любому объекту TextField;
? может перетаскиваться с помощью мыши для прокрутки поля по вертикали;
? автоматически обновляется в ответ на изменения в размерах поля, его содержимого или позиции прокрутки.
Руководство по actionscript. часть 4, стр. 085
Тем не менее для простоты данная полоса прокрутки не включает кнопки для прокручивания содержимого вниз и вверх. В листинге 22.15 применяются многие методики, которые были рассмотрены в этой главе, а также несколько еще не описанных методик. Там, где это необходимо, указаны перекрестные ссылки на дополнительные темы.
Листинг 22.15. Использование события Event. SCROLL для реализации полосы прокрутки
package { import flash. display.*; import flash. text.*: import flash. events.*: import flash. utils.*; import flash. geom.*;
// Простая полоса прокрутки с возможностью перетаскивания, которая // автоматически обновляется в ответ на изменения в размерах заданного // текстового поля. // Использование:
// var theTextField:TextField = new TextField( );
// someContai ner. addChi1d(theTextFi eld);
// var scrollbar:ScrollBar = new ScrollBar(theTextField);
// someContai ner. addChi 1 d(scrol 1 bar);
public class Scrol1 Bar extends Sprite { // Текстовое поле, к которому применяется данная полоса прокрутки private var t:TextField;
// Текущая высота текстового поля. Если высота текстового поля
// изменяется, мы обновляем высоту данной полосы прокрутки.
Руководство по actionscript. часть 4, стр. 086
Private var tHeight:Number;,
// Фоновое изображение для полосы прокрутки
private var scrollTrack:Sprite;
// Перетаскиваемый ползунок полосы прокрутки
private var scrolIThumbiSprite;
// Ширина полосы прокрутки
private var scrolIbarWidth:int = 15;
// Минимальная высота ползунка полосы прокрутки
private var minimumThumbHeight:int = 10;
// Флажок, который обозначает, перетаскивает ли пользователь ползунок // в данный момент
private var dragging:Boolean = false;
// Флажок, который обозначает, нужно ли перерисовывать полосу прокрутки // на следующем запланированном этапе обновления экрана private var changed:Boolean = false;
// Конструктор.
Руководство по actionscript. часть 4, стр. 087
// @param textfield Объект TextField, к которому применяется данная
// полоса прокрутки.
public function Scrol1 Bar (textfield:TextField) {
// Сохраняем ссылку на объект TextField, к которому применяется данная
// полоса прокрутки
t = textfield;
// Запоминаем высоту текстового поля, чтобы мы могли отслеживать // изменения, требующие перерисовки полосы прокрутки.
// Создаем фон полосы прокрутки
scrollTrack = new Sprite( );
scrol1 Track. graphics. lineStyle( );
scrol1 Track. graphi cs. begi nFi11 (0×333333);
scrollTrack. graphics. drawRect(0, 0, 1. 1);
addChild(scrollTrack);
// Создаем перетаскиваемый ползунок на полосе прокрутки
scrolIThumb = new SpriteC );
scroll Thumb. graphics. lineStyle( );
scrolIThumb. graphics. beginFi11(OxAAAAAA);
scrolIThumb. graphics. drawRecUO. 0, 1, 1);
addChild(scrolIThumb);
// Регистрируем приемник события Event. SCROLL, который будет обновлять // полосу прокрутки в соответствии с текущей позицией прокрутки поля t. addEventListener(Event. SCROLL. scrolHistener);
// Регистрируем в объекте scrolIThumb приемник для событий нажатия
// кнопки мыши, который будет вызывать перетаскивание ползунка
scrol1 Thumb. addEventLi stener(MouseEvent. M0USE_D0WN. mouseDownLi stener);
// Регистрируем приемник для получения уведомлений, когда данный // объект добавляется в список отображения или удаляется из него // (требуется пользовательский вспомогательный класс StageDetector). // Когда данный объект добавляется в список отображения, регистрируем // приемники для событий перемещения мыши и отпускания кнопки мыши // на уровне объекта stage, которые будут управлять операцией // перетаскивания ползунка.
Руководство по actionscript. часть 4, стр. 088
Var StageDetector:StageDetector = new StageDetector(this); StageDetector. addEventLi stener(StageDetector. ADDED_TO_STAGE.
addedToStageLi stener); StageDetector. addEventLi stener(StageDetector. REMOVED_FROM_STAGE,
removedFromStageListener);
// Регистрируем приемник для получения уведомлений перед каждым
// обновлением экрана. Перед обновлением экрана проверяем,
// требуется ли перерисовка полосы прокрутки. Информацию по событию
// Event. ENTER_FRAME можно найти в гл. 24.
addEventListener(Event. ENTER_FRAME. enterFrameListener);
// Инициируем первоначальную прорисовку полосы прокрутки, changed = true;
-}
// Выполняется всякий раз, когда данный объект добавляется // в список отображения
private function addedToStageListener (e:Event):void { // Регистрируем приемники для «глобальных» событий перемещения мыши // и отпускания кнопки мыши
stage. addEventLi stener(MouseEvent. MOUSEJJP. mouseUpLi stener); stage. addEventLi stener(MouseEvent. M0USE_M0VE, mouseMoveLi stener);
}
// Выполняется всякий раз. когда данный объект удаляется // из списка отображения
private function removedFromStageListener (e:Event):void { // Отменяем регистрацию приемников для «глобальных» событий // перемещения мыши и отпускания кнопки мыши stage. removeEventListener(MouseEvent. MOUSEJJP, mouseUpListener); stage. removeEventLi stener(MouseEvent. M0USE_M0VE, mouseMoveLi stener);
}
// Выполняется один раз для каждого обновления экрана. Этот метод // проверяет, произошли ли какие-либо изменения в позиции прокрутки // текстового поля, его содержимом или размерах с момента последней // перерисовки полосы прокрутки. Если да. то перерисовываем полосу // прокрутки. Выполняя эту проверку — «рисовать или нет» — всего один // раз перед обновлением экрана, мы избавляемся от ненужных вызовов // метода updateScrol1bar( ), а также избегаем проблем в приложении // Flash Player, связанных с задержкой при изменении значения переменной // TextField. maxScrolIV.
Руководство по actionscript. часть 4, стр. 089
Private function enterFrameListener (e:Event):void { // Если высота поля изменилась, запрашиваем перерисовку // полосы прокрутки
if (t. height!= tHeight) { changed = true; tHeight = t. height;
// Высота изменилась, поэтому прекращаем любую // в настоящий момент операцию перетаскивания. // будет вынужден щелкнуть снова, чтобы начать // перетаскивания ползунка после перерисовки // полосы прокрутки, if (dragging) {
scrol1 Thumb. stopDrag( );
dragging = false;
}
}
// Если требуется перерисовка полосы прокрутки… if (changed) {
// …вызываем процедуру отрисовки полосы прокрутки
updateScrollbar( );
changed = false;
}
}
// Обрабатывает события Event. SCROLL
private function scrolIListener (e:Event):void { // В определенных случаях, когда строки удаляются из текстового поля. // приложение Flash Player выполняет диспетчеризацию двух событий: // одно событие связано с уменьшением значения переменной maxScrol1V // (диспетчеризация осуществляется немедленно), а другое -// с уменьшением значения переменной scrolIV (диспетчеризация // осуществляется спустя несколько обновлений экрана). В подобных // ситуациях переменная scrolIV некоторое время имеет неправильное // значение, которое превышает значение переменной maxScrolIV. // В качестве обходного пути мы игнорируем событие, возникающее // после изменения значения переменной maxScrol1V, и ожидаем // появления события, возникающего в результате изменения значения // переменной scrolIV (в противном случае отрисованная полоса // прокрутки некоторое время не будет соответствовать фактическому // содержимому поля), if (t. scrolIV > t. maxScrollV) { return;
}
// Если на данный момент пользователь не перетаскивал ползунок полосы
// прокрутки, помечаем, что данная полоса прокрутки должна быть
// перерисована на следующем запланированном этапе обновления экрана.
Руководство по actionscript. часть 4, стр. 090
// (Если в данный момент пользователь перетаскивает ползунок,
// изменение прокрутки, вызвавшее данное событие, явилось результатом
// перетаскивания ползунка в новую позицию, поэтому обновлять полосу
// прокрутки не нужно, поскольку ползунок уже находится в правильной
// позиции.)
if (!dragging) {
происходящую Пользователь операцию
changed = true;
}
}
// Устанавливает размеры и позицию фонового изображения и ползунка // полосы прокрутки в соответствии с размерами и содержимым связанного // текстового поля. Информацию о переменных scrolIV, maxScrolIV // и bottomScrollV класса TextField можно найти в справочнике // по языку ActionScript корпорации Adobe, public function updateScrollbar ( ):void {
// Устанавливаем размеры и позицию фонового изображения полосы прокрутки.
Руководство по actionscript. часть 4, стр. 091
// Данный код всегда помещает полосу прокрутки справа от поля.
scrollTrack. х = t. x + t. width;
scrollTrack. y = t. y;
scrollTrack. height = t. height;
scrol lTrack. width = scrollbarWidth;
// Проверяем количество видимых на экране строк текстового поля
var numVisibleLines:int = t. bottomScrollV — (t. scrol1V-1);
// Если часть строк в текстовом поле не видна на экране…
if (numVisibleLines < t.numlines) { // ...отображаем ползунок scrolithumb.visible = true; // теперь устанавливаем размеры ползунка // высота ползунка определяется процентным соотношением // отображаемых строк, умноженным на высоту текстового поля var thumbheight:int = math.floor(t.height *
(numVi siblel_i nes/t. numLi nes)); // Высота ползунка не должна быть меньше значения minimumThumbHeight scrolIThumb. height = Math. max(minimumThumbHeight, thumbHeight); scrolIThumb. width = scrollbarWidth;
// Теперь устанавливаем позицию ползунка scrollThumb. x = t. x + t. width;
// Вертикальная позиция ползунка определяется количеством // прокрученных строк в поле, выраженным в процентах и умноженным // на высоту «пространства полосы» (это высота // полосы прокрутки за вычетом высоты ползунка), scrolIThumb. y = t. y + (scrollTrack. height-scrolIThumb. height) * ((t. scrol 1V-D/U. maxScrol 1V-D);
} else { •
// Если в данный момент на экране отображаются все строки текстового // поля, прячем ползунок полосы прокрутки scrolIThumb. visible = false;
}
// Устанавливает вертикальную позицию прокрутки текстового поля // в соответствии с относительной позицией ползунка public function synchTextToScrolIThumb ( ):void {
var scrolIThumbMaxY:Number = t. height-scrollThumb. height;
var scrolIThumbY:Number = scrolIThumb. y-t. у;
t. scrolIV = Math. round(t. maxScrolIV
* (scrol1ThumbY/scrol1ThumbMaxY));
}
// Выполняется, когда пользователь нажимает основную кнопку мыши // над ползунком
private function mouseDownListener (e:MouseEvent):void { // Начинаем операцию перетаскивания ползунка. (Метод startDrag( ) // наследуется из класса Sprite.) var bounds:Rectangle = new Rectangle(t. x + t. width,
t. y.
Руководство по actionscript. часть 4, стр. 092
0,
t. height-scrolIThumb. height); scrollThumb. startDrag(false, bounds); dragging = true;
}
// Выполняется, когда пользователь отпускает основную кнопку мыши // (в любом месте области отображения приложения Flash Player и даже // за ее пределами)
private function mouseUpListener (e:MouseEvent):void { // Если пользователь перетащил ползунок, обновляем вертикальную // позицию прокрутки поля, после чего прекращаем операцию // перетаскивания ползунка if (dragging) {
synchTextToScrollThumb( );
scrolIThumb. stopDragC );
dragging = false;
}
}
// Выполняется при перемещении указателя мыши (над областью отображения // приложения Flash Player)
private function mouseMoveListener (e:MouseEvent):void { // Если пользователь перетаскивает ползунок, устанавливаем // вертикальную позицию прокрутки в соответствии с относительной // позицией ползунка if (dragging) { synchTextToScrolIThumbC );
}
}
}
}
В листинге 22.16 представлен простой тестовый класс, который демонстрирует использование класса БсгоИВагиз листинга 22.15.