Просмотр полной версии : MovieClip не принимает сообщение от родителя
Есть два класса - app (главный класс флэшки) и receiver (класс находящегося на сцене movie clip, по сути - потомок app);
app посылает сообщение и задача receiver - его услышать. receiver его не слышит. Полагаю, я плохо понимаю механизм посылки сообщений. Если кто либо может взглянуть на пример кода и поправить меня, буду очень благодарен.
В приложенном файле весь пример целиком, а вот сам код
app:
package{
import flash.display.MovieClip;
import flash.events.ProgressEvent;
import flash.events.Event;
public class app extends MovieClip{
public function app(){
loaderInfo.addEventListener(ProgressEvent.PROGRESS,onProgress);
}
public function onProgress(e:ProgressEvent):void {
dispatchEvent(new Event('APP_PROGRESS'));
trace('message sended');
}
}
}
receiver:
package{
import flash.display.MovieClip;
import flash.events.Event;
public class receiver extends MovieClip{
public function receiver(){
addEventListener('APP_PROGRESS', onMessage);
}
public function onMessage(e:Event):void{
trace('message received');
}
}
}
Mr. Fixit
03.03.2008, 22:20
ты же пиши кому извещать..
создай например глобальный инстанс и к нему крепи листенеры..
Что значит "пиши, кому извещать"? Извещает app. Он - верхний в иерархии класс, глобальнее вроде некуда. А если "кого извещать" - если бы app знал имена потомков то не было бы смысла в сообщениях - проще методы потомков вызывать
можно написать :
root.addEventListener('APP_PROGRESS', onMessage);
и сообщение принимается, но в документации при работе с сообщениями я таких финтов не вижу. Как я понял, сообщение сходит по дереву иерархии вниз, а если указать
dispatchEvent(new Event('APP_PROGRESS',true));
то и всплывает до самого верха.
Я хочу понять принцип ошибки - где я не понял теорию? - иначе то что я делаю больше похоже на хак.
можно написать :
root.addEventListener('APP_PROGRESS', onMessage);
и сообщение принимается, но в документации при работе с сообщениями я таких финтов не вижу. root у вас это app, поэтому обработчик в этом случае благополучно вносится в массив слушателей.
если бы app знал имена потомков то не было бы смысла в сообщениях - проще методы потомков вызывать Проще -- далеко не всегда правильнее.
ps: Названия классов пишутся с большой буквы, а обработчики приватные немешало бы сделать.
А кто вас так научил классы называть и не научил кастомным событиям?
terbooter
04.03.2008, 07:59
Знаю как сделать чтоб работало, но не понимаю почему не работает этот пример. Присоединяюсь к вопросу автора
Нужно использовать всплывающие события. Никаких хаков тут нет, событие от детей поднимается вверх по родителям. Если не использовать bubbling, то событие попадет только в те обработчики, которые были подписаны непосредственно у того, кто шлет событие.
akerka,
проблемы с твоим кодом возникают из-за идеологически неверно простроеных отношений между классами.
Добиться работоспособности можно, используя bubbling и targeting. Но код в итоге получится корявым.
Что делать:
1. Переименовать. Да-да. Нет слова app в английском. А сократить так можно и appendix и application и, думаю еще не одно слово. Код пишется в первую очередь для человека. Ну, и учесть, что имена классов начинаются с большой буквы.
Это - самое важное. Остальное мелочи.
2. Где-то у тебя создается экземпляр класса receiver (но мы договорились, что переименуем этот класс на более понятное, что-то типа ApplicationPreloaderReceiver). Вот там, где он создается, и нужно передать ссылку на экземпляр класса ныне именуемого app.
И, затем, подпишемся на его события.
зачеркнуто И, затем, подпишем его на события этого класса. /зачеркнуто
3. В коде мы не будем использовать строки и навешивать нехарактерное вещание на класс Event. Просто создадим класс - наследник Event, например ApplicationPreloaderEvent и создадим в нем публичную статическую константу
APPLICATION_PROGRESS:String = "applicationProgress"
и в дальнейшем в коде будем использовать только ее для вещания событий этого типа.
Примерно так.
Теоретически возможно, что передать ссылку на экземпляр app будет затруднительно. В этом случае, коль уж это так тяжело, этот класс следует во-первых переименовать например: MyFirstApplication, а во-вторых сделать его синглтоном и подписываться на событие используя получение ссылки через getInstance(). Впрочем, это не рекомендуемая практика.
удачи.
2. Каким образом? Откроем всем ветрам приватные обработчики событий?
Чем это бабблинг корявый вдруг стал?
п.2 спасибо, Денис. Там была ошибка по тексту. Исправил.
Баблинг не стал корявым. И тут я ошибся, только в другую сторону: с помощью баблинга вроде как нельзя проинформировать детей.
Так что описаная ситуация невозможна.
Впрочем, я могу ошибаться, не проверял.
Вообще, что касается событий, я бы сказал, что это штука довольно мощная, однако подходить к использованию событий надо с умом и осторожностью.
Теоретически, все вызовы методов можно заменить событиями, однако этого никто не делает, поскольку это усложняет восприятие логики приложения.
Соответственно есть некая грань, которую нужно довольно четко понимать и думать, а стоит ли использовать именно событие.
terbooter
05.03.2008, 08:08
Думаю уместно задать здесь свой вопрос.
Читаю справку и блок Constantiner-a (http://riapriority.com/blogs/constantiner.php/2008/01/22/event_bubbling_again)
пытаюсь разобраться с Event flow. Я представляю себе это так: есть некий объект из дисплэй листа, сам по себе он никагого события из вне отловить не может (естественно), например, нажатие мыши. Флэш плеер говорит этому объекту, знаешь, дорогой генери такое-то событие. (В АС2 было только так). Но в АС3 это событие исходит не сразу от объекта источника, а движется от среды (Flash Player) к этому объекту. Не спроста есть свойство target, название которого как-то замыливается, но если подумать, почему объект стал целью, если он источник. А вот оказывается, он "цель" для события которое имеет точку входа stage.
Это что касается событий которые "из-вне" (клики, загрузка, девайсы...)
Тут мне все понятно, процессом можно управлять: "пузырить", "не пузырить", прекращать распространение и тд.
Не понятно есть ли какой-то поток событий для событий генерируемых "внутри"? Или тут урезанная программа возможна только стадия пузырька?
stage.sprite1.sprite2.sprite3.dispatchEvent(new Event("testEvent", true));
п.2 спасибо, Денис. Там была ошибка по тексту. Исправил.
Баблинг не стал корявым. И тут я ошибся, только в другую сторону: с помощью баблинга вроде как нельзя проинформировать детей.
Так что описаная ситуация невозможна.
Впрочем, я могу ошибаться, не проверял.
Вообще, что касается событий, я бы сказал, что это штука довольно мощная, однако подходить к использованию событий надо с умом и осторожностью.
Теоретически, все вызовы методов можно заменить событиями, однако этого никто не делает, поскольку это усложняет восприятие логики приложения.
Соответственно есть некая грань, которую нужно довольно четко понимать и думать, а стоит ли использовать именно событие.
Бабблинг работает от ребенка к родителю, да.
Что касается вызовов методов, то я по своему опыту могу сказать, что у меня прямые вызовы методов составляют где-то процентов 30 от всех…
terbooter, не очень понял твой вопрос.
terbooter
05.03.2008, 09:19
Если коротко, то:
Существует ли поток событий если объект генерит событие с помощью
dispatchEvent
Если коротко, то:
Существует ли поток событий если объект генерит событие с помощью
dispatchEvent
В смысле бабблинг? Существует, конечно.
Вообще говоря, ничего сложного в работе EventDispatcher нет.
terbooter
05.03.2008, 09:26
Никак не могу сделать примерчик, где событие генерится dispatchEvent,
а у какого-нибудь слушателя оно отрабатывается при этом target != currentTarget или eventPhase != 2;
Пытаюсь делать так:
//пишу код прямо в кадре для быстроты
var s:Sprite=new Sprite();
addChild(s);
s.dispatchEvent(new Event("testEvent",true));
stage.addEventListener("testEvent",testEventHandler);
function testEventHandler(e:Event):void {
trace(e);
}
(кастомный ивент мне было лень писать):
package {
import flash.display.Sprite;
import flash.events.Event;
public class Dispatcher extends Sprite {
public function Dispatcher() {
super();
super.addEventListener(Event.ENTER_FRAME, this.enterFrameHandler);
}
private function enterFrameHandler(event:Event):void {
super.dispatchEvent(new Event('custom', true));
}
}
}
package {
import flash.display.Sprite;
import flash.events.Event;
public class Listener extends Sprite {
public function Listener() {
super();
super.addEventListener('custom', this.customHandler);
super.addChild(new Dispatcher());
}
private function customHandler(event:Event):void {
trace(event);
}
}
}
На выходе получаем:
[Event type="custom" bubbles=true cancelable=false eventPhase=3]
[Event type="custom" bubbles=true cancelable=false eventPhase=3]
[Event type="custom" bubbles=true cancelable=false eventPhase=3]
[Event type="custom" bubbles=true cancelable=false eventPhase=3]
[Event type="custom" bubbles=true cancelable=false eventPhase=3]
[Event type="custom" bubbles=true cancelable=false eventPhase=3]
[Event type="custom" bubbles=true cancelable=false eventPhase=3]
terbooter
05.03.2008, 09:45
Мой пример тоже заработал !
stage.addEventListener("testEvent",testEventHandler);
function testEventHandler(e:Event):void {
trace(e);
}
var s:Sprite=new Sprite();
addChild(s);
s.dispatchEvent(new Event("testEvent",true));
Это же волшебно! Теперь не буду париться и для каждого блока контроллеров весить листенер. Все листенеры буду весить прямо на сцену.
Все листенеры буду весить прямо на сцену.
Очень опрометчивое решение.
Прям копи-пастом:
Для передачи событий из View (MVC) удобно использовать bubbling в сочетании со stopPropagation() там, где не требуется дальнейшее всплытие события.
В итоге все события View отлавливаются в Main и далее перенаправляются куда требуется.
Прям копи-пастом:
Для передачи событий из View (MVC) удобно использовать bubbling в сочетании со stopPropagation() там, где не требуется дальнейшее всплытие события.
В итоге все события View отлавливаются в Main и далее перенаправляются куда требуется.
Сори, хотел поинтересоваться, вот к примеру у меня есть класс меню, в нем класс итема, я вешаю генерацию события на итем - notify(), как теперь словить это событие на сцене??
1 событие должно быть с баблингом
2 ты просто в рутовом классе пишешь addEventListener(MyMenuEvent.NOTIFY, onItemNotify);
примерно так
Работает на vBulletin ® версия 3.7.3. Copyright ©2000-2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Copyright © 1999-2008 Flasher.ru. All rights reserved.