Просмотр полной версии : правильно пишем метод-обработчик события
1) Новая событийная модель не может не радовать :cool: Однако, "пузырьковость" евентовых объектов, заставляет сменить AS 2.0 тактику написания обработчиков ивентов, а именно, если говорить простыми словами, раньше target был один, а теперь их целая последовательность. Возникает вопрос, как грамотно обработать ивент, только для нужного нам объекта (на ум пока приходит только проверка типов для event.target и event.currentTarget, что выглядит довольно коряво (см.пример))?
2) Плюс, столкнулся с проблемой для mx.containers.TitleWindow (хочу задачть обрабочика на клик по клоузбаттону) - ивент click (Events inherited from class Panel) . Проблема в том, что аналогичный ивент генерится и просто при клике на инстанс TitleWindow - ивент click (Events inherited from class UIComponent). Как отличить два случая? В примере окошко закрывается не только в случае клика по кнопке close, но и при клике на титл окна.
Вот код по обоим примерам:
package classes.ui {
public class ImageWindow extends TitleWindow {
public function ImageWindow(){
className = "ImageWindow";
}
override public function initialize():Void{
super.initialize();
addEventListener(MouseEventType.CLICK, onClick);
}
private function onClick(event:MouseEvent):Void{
if((event.currentTarget is ImageWindow)){
if(event.target is ImageWindow){
WindowManager.closePopUp(event, event.currentTarget);
}else{
WindowManager.riseWindow(event, event.currentTarget);
}
}
}
}
}
а почему таргетов целая последовательность? таргет при клике только один.
ну отследи фазу capture....
event.eventPhase == 1
посмотри кто таргет,
если таргет клосбатон - то выполняй свое действие и отменяй распостранение эвента, или не отменяй.
хотя как бы фазу capture отслеживать и незачем.. ведь отдельный обработчик для этого....
кстати я не совсем понимаю назначение currentTarget.... может пояснишь,
я трейсю при клике у меня всегда таргет Stage.... я тестирую просто на спрайтах, может в компонентах по другому,
как я понял currentTarget - это верхний в иерархии объект, от которого начинается распостраниение фазы capture и заканчивается фаза bubble... или по другому как?
о! какой Stage. я ведь к Stage добавил обработчик события,
теперь понял для чего currentTarget....
currentTarget нужен тогда когда один и тот же обработчик (метод/функия) используется несколько раз при обработки события,
например при обработки capture фазы я добавил обработчик руту и вложненному в него спрайту,
мне нужно узнать где, в каком контексте обрабатывается событие, чей addEventListener был использован при регистрации хендлера.
но target все равно будет один.
Хм, видим ос компонентами все сложнее. Пример для mx.containers.TitleWindow:
private function onClick(event:MouseEvent):Void{
trace("-----");
trace(event.target);
}
//output:
-----
ImageWindow_22
ImageWindow_22.UIComponent_23.Button_26
-----
[object Loader]
В первом случае кликал на клозбатон, во-втором на тело окошка (в теле Image (отнаследованный от Loader), хотя на него я никаких обработчиков не вешал).
Т.е. кроме инстанса TitleWindow так же подписываются еще куча обектов и для всех них дергается один и тот же метод с разными таргетами.
Вот более полный лог (условия те же):
-----
target = [object Loader], currentTarget=ImageWindow_22
-----
target = ImageWindow_22, currentTarget=ImageWindow_22
-----
target = ImageWindow_22.UIComponent_23.Button_26, currentTarget=ImageWindow_22
Т.е. currentTarget всегда один (тот на кого я повеси обработчик), а вот target разные (объект, по которому я кляцаю).
И все-таки по теме сабжа, выходит if'ы лепить - единсвенный метод буть уверенным, что target - нужный тебе обект (пока работаю с флексом вторым, так что говорю только о компонентах, со спрайтами особо не возился, судя по постам Джона там дела обстоят иначе :) ) ?
чтото не понимаю я вопроса/задачи....
ну кликнул на элемент - он и таргет получается, или чтото не так?
давай с постановки задачи, что нужно добиться?
какие симптомы проблемы?
и полный пример в студию....
В общем так:
Задача - закрыть окошко по клику на клозбатон (клозбатон встроеный, прямой ссылки на себя не имеет. В мане написано, что TitleWindow генерит click, когда кликают на клозбатон - собсвенный ивент класса TitleWindow).
Имеем - одно окно (см код из головного поста). На него вешается один раз обработчик (в initialize) - все, больше никаких обработчиков нигде нет. (Тут имеется подводный камень: TitleWindow имеет унаследованный от UIComponent ивент click ! (вот надо ж было девелоперам из ММ назвать 2 РАЗНЫХ ивента одинакого) - этот ивент дергается, когда мы кликаем на любое место TitleWindow, таким образом при клике на клозбатон обработчик дергается дважды).
Получаем: В обработчике получаем кашу из target'ов.. При клике на склозбатом таргктом является она, при клике на контен TitleWindow (там у нас лежит Image отнаследованный от Loader) таргетом является Loader, а при клике на чисто TitleWindow таргетом является сам TitleWindow, а currentTarget всегда один -TitleWindow, имхо это расходится с тем, что ты писал, Джон?
Таким образом главная проблема - как отловить нажание именно на клозбатон? Прямой ссылки мы на его инстанс не имеем, чтобы сделать проверку на равенство target и клозбатона, а проверка по типу (Button) ни к чему не ведет, т.к. в теле окна, может быть куча других баттонов.
Спасибо новоприбывшему человеку (теперь я знаю -- его зовут Филипп) за хорошую тему.
У меня вопрос: почему бы не воспользоваться определением состояния, сравнивая его с EventPhase.AT_TARGET ?
да.. странно все это,
ну таргеты ты разные получешь - это понятно,
потому что перехватываешь bubble фазу, и тебе шлется все подряд - в какую область окна не кликнули. Тут все тоже что и со спрайтами, уникального поведения не вижу.
Нужно както докопаться до closeButton чтобы на нее навесить событие, а вот как это сделать, я не понял. Сейчас еще пороюсь. Похоже это вопрос - знаю как... эх документации не хватает.
Отключить bubbling, не будет пузырькового эффекта. Сверять стадию на равенство EventPhase.AT_TARGET.
Проверил фазу для всех случаев. Ниже приведен лог в случае клика на клозбатон, в случае клика на инстансе TitleWindow и в случае клика на картинку (в теле TitleWindow):
Кликаем на TitleWindow
-----
target = ImageWindow_22, currentTarget=ImageWindow_22, eventPhase =2
Кликаем на клозбатон: <<<
-----
target = ImageWindow_22, currentTarget=ImageWindow_22, eventPhase =2
-----
target = ImageWindow_22.UIComponent_23.Button_26,
currentTarget=ImageWindow_22, eventPhase =3
Кликаем на картинку
-----
target = [object Loader], currentTarget=ImageWindow_63, eventPhase =3
Нужный нам случай помечен <<<. Интерсено, что первый случай, полностью (?) совпадает с первой строкой втого случая, именно в этом и загвоздка, непонятно, как это дело различить..
Как его отловить?
Отключить bubbling, не будет пузырькового эффекта. Сверять стадию на равенство EventPhase.AT_TARGET.
а смысл? таргет фазу ведь все равно получить не можем, в смысле таргет фазу close button. Нет доступа к ней. Вот только в баблинг и в capture и можно перехватывать.
Antares Да, надо попробовать. Тогда вопрос:
Как правильно отключить баблинг? Пробовал в теле обработчика - эффекта не заметил, пробовал оба метода stopImmediatePropagation() и stopPropagation().
Код:
private function onClick(event:MouseEvent):Void{
event.stopImmediatePropagation();
Logger.msg("-----");
Logger.msg("target = "+event.target+", currentTarget="+event.currentTarget+", eventPhase ="+event.eventPhase );
if((event.currentTarget is ImageWindow)){
if(event.target is ImageWindow){
//Logger.msg("going close", event.target);
WindowManager.closePopUp(event, event.currentTarget);
}else{
WindowManager.riseWindow(event, event.currentTarget);
}
}
}
BlooDHounD
27.12.2005, 01:41
Никогда не был силён в компанентах, и врят ли буду, так не люблю готовое. В общем я конечно могу тупить, так в чём проблема написать свой евент наследованный от Event? там в конструктор напрямую передаёшь, что надо, а что не надо. Любые таргеты и включаешь выключаешь бублинги и любую бредятину которую ты захочешь запихнуть в событие.
BlooDHounD
27.12.2005, 01:54
ну вот пример моего события ... оно конечно примитивно ... но для моего случия подходит :)package game.events
{
import flash.events.Event;
public final class MonsterEvent extends Event
{
private var m_direction:String;
public function MonsterEvent(type:String, direction:String, bubbles:Boolean=false, cancelable:Boolean=false)
{
super(type, bubbles, cancelable);
this.m_direction = direction;
}
public override function clone():Event
{
return new MonsterEvent(this.type, this.m_direction, this.bubbles, this.cancelable);
}
public override function toString():String
{
return formatToString("MonsterEvent", "type", "direction", "bubbles", "cancelable");
}
public function get direction():String
{
return this.m_direction;
}
}
}Юзается это потом приблизительно так: private function doMove(event:Event):Void
{
switch (this._direction)
{
case MonsterDirection.LEFT: this.x -= this._speed; break;
case MonsterDirection.RIGHT: this.x += this._speed; break;
case MonsterDirection.TOP: this.y -= this._speed; break;
case MonsterDirection.BOTTOM: this.y += this._speed; break;
default: return;
}
this.dispatchEvent(new MonsterEvent(MonsterEventType.MONSTER_MOVE, this._direction));
}
Блуд прав, просто наследовать от Event, в конструкторе после super() отключить бабблинг
2Antares,
не понял я - причем тут перезначать, ну работали бы со своими собыитиями - ну хорошо,
тут ведь задача стоит перехватить событие клика у окна, и события шлет оно само как хочет, причем тут перезначать?
да и не вижу я проблемы в баблинге - он тут как раз помошник чем вредитель :)
мы не имеем ссылки на таргет (клос-баттон) физически, поэтому можем получать либо баблинг, либо кэпчур.
Отключить то легко, как ты писал - просто игнорировать фазу (if(event.eventPhase == 3)return).
не в этом вопрос, а как эффективно использовать эвент модель, в данном конкретном примере, без хаков и прыжков через голову.
Я просто обобщил.
Конкретно по этому случаю меня смущает одно: у компонентов есть событие некого класса UIEvent, найти который в доке к альфа 1 не представляется возможным.
А что-то подсказывает, что там есть нужное, так сказать, для полноты картины
вот нашел кое какое решение -
public function doClick(e:MouseEvent){
if(titleBar.contains(e.target))
{
PopUpManager.removePopUp(this);
}
}
то есть проверяем является ли таргет частью titleBar, как не странно но titleBar не шлет события клика, драг есть, а клика нет, вероятно это сделано специально для отслеживания close....
ну во всяком случае работает.
думаю TitleWindow компонент еще не совсем готов, думаю должны быть события типа "сlose", например TitleEvent.CLOSE
По-крайней мере, логично этого ожидать
Да, титлбар ивента не шлет, тоже это сразу заметил.
john
Спасибо за способ :)
Всем спасибо за проявленый интерес!
Работает на vBulletin ® версия 3.7.3. Copyright ©2000-2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Copyright © 1999-2008 Flasher.ru. All rights reserved.