Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   MovieClip не принимает сообщение от родителя (http://www.flasher.ru/forum/showthread.php?t=108931)

akerka 03.03.2008 22:14

MovieClip не принимает сообщение от родителя
 
Вложений: 1
Есть два класса - 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

ты же пиши кому извещать..
создай например глобальный инстанс и к нему крепи листенеры..

akerka 03.03.2008 22:27

Что значит "пиши, кому извещать"? Извещает app. Он - верхний в иерархии класс, глобальнее вроде некуда. А если "кого извещать" - если бы app знал имена потомков то не было бы смысла в сообщениях - проще методы потомков вызывать

akerka 03.03.2008 22:38

можно написать :
Код:

root.addEventListener('APP_PROGRESS', onMessage);
и сообщение принимается, но в документации при работе с сообщениями я таких финтов не вижу. Как я понял, сообщение сходит по дереву иерархии вниз, а если указать
Код:

dispatchEvent(new Event('APP_PROGRESS',true));
то и всплывает до самого верха.

Я хочу понять принцип ошибки - где я не понял теорию? - иначе то что я делаю больше похоже на хак.

udaaff 03.03.2008 23:38

Цитата:

Сообщение от akerka
можно написать :
Код:

root.addEventListener('APP_PROGRESS', onMessage);
и сообщение принимается, но в документации при работе с сообщениями я таких финтов не вижу.

root у вас это app, поэтому обработчик в этом случае благополучно вносится в массив слушателей.
Цитата:

если бы app знал имена потомков то не было бы смысла в сообщениях - проще методы потомков вызывать
Проще -- далеко не всегда правильнее.

ps: Названия классов пишутся с большой буквы, а обработчики приватные немешало бы сделать.

etc 04.03.2008 00:00

А кто вас так научил классы называть и не научил кастомным событиям?

terbooter 04.03.2008 07:59

Знаю как сделать чтоб работало, но не понимаю почему не работает этот пример. Присоединяюсь к вопросу автора

etc 04.03.2008 09:18

Нужно использовать всплывающие события. Никаких хаков тут нет, событие от детей поднимается вверх по родителям. Если не использовать bubbling, то событие попадет только в те обработчики, которые были подписаны непосредственно у того, кто шлет событие.

Iv 04.03.2008 21:03

akerka,
проблемы с твоим кодом возникают из-за идеологически неверно простроеных отношений между классами.
Добиться работоспособности можно, используя bubbling и targeting. Но код в итоге получится корявым.

Что делать:

1. Переименовать. Да-да. Нет слова app в английском. А сократить так можно и appendix и application и, думаю еще не одно слово. Код пишется в первую очередь для человека. Ну, и учесть, что имена классов начинаются с большой буквы.
Это - самое важное. Остальное мелочи.

2. Где-то у тебя создается экземпляр класса receiver (но мы договорились, что переименуем этот класс на более понятное, что-то типа ApplicationPreloaderReceiver). Вот там, где он создается, и нужно передать ссылку на экземпляр класса ныне именуемого app.
И, затем, подпишемся на его события.

зачеркнуто И, затем, подпишем его на события этого класса. /зачеркнуто

3. В коде мы не будем использовать строки и навешивать нехарактерное вещание на класс Event. Просто создадим класс - наследник Event, например ApplicationPreloaderEvent и создадим в нем публичную статическую константу
APPLICATION_PROGRESS:String = "applicationProgress"
и в дальнейшем в коде будем использовать только ее для вещания событий этого типа.

Примерно так.

Теоретически возможно, что передать ссылку на экземпляр app будет затруднительно. В этом случае, коль уж это так тяжело, этот класс следует во-первых переименовать например: MyFirstApplication, а во-вторых сделать его синглтоном и подписываться на событие используя получение ссылки через getInstance(). Впрочем, это не рекомендуемая практика.

удачи.

etc 05.03.2008 00:26

2. Каким образом? Откроем всем ветрам приватные обработчики событий?
Чем это бабблинг корявый вдруг стал?

Iv 05.03.2008 01:09

п.2 спасибо, Денис. Там была ошибка по тексту. Исправил.

Баблинг не стал корявым. И тут я ошибся, только в другую сторону: с помощью баблинга вроде как нельзя проинформировать детей.
Так что описаная ситуация невозможна.
Впрочем, я могу ошибаться, не проверял.

Вообще, что касается событий, я бы сказал, что это штука довольно мощная, однако подходить к использованию событий надо с умом и осторожностью.
Теоретически, все вызовы методов можно заменить событиями, однако этого никто не делает, поскольку это усложняет восприятие логики приложения.
Соответственно есть некая грань, которую нужно довольно четко понимать и думать, а стоит ли использовать именно событие.

terbooter 05.03.2008 08:08

Думаю уместно задать здесь свой вопрос.
Читаю справку и блок Constantiner-a
пытаюсь разобраться с Event flow. Я представляю себе это так: есть некий объект из дисплэй листа, сам по себе он никагого события из вне отловить не может (естественно), например, нажатие мыши. Флэш плеер говорит этому объекту, знаешь, дорогой генери такое-то событие. (В АС2 было только так). Но в АС3 это событие исходит не сразу от объекта источника, а движется от среды (Flash Player) к этому объекту. Не спроста есть свойство target, название которого как-то замыливается, но если подумать, почему объект стал целью, если он источник. А вот оказывается, он "цель" для события которое имеет точку входа stage.
Это что касается событий которые "из-вне" (клики, загрузка, девайсы...)
Тут мне все понятно, процессом можно управлять: "пузырить", "не пузырить", прекращать распространение и тд.

Не понятно есть ли какой-то поток событий для событий генерируемых "внутри"? Или тут урезанная программа возможна только стадия пузырька?
Код:

stage.sprite1.sprite2.sprite3.dispatchEvent(new Event("testEvent", true));

etc 05.03.2008 09:11

Цитата:

Сообщение от Iv
п.2 спасибо, Денис. Там была ошибка по тексту. Исправил.

Баблинг не стал корявым. И тут я ошибся, только в другую сторону: с помощью баблинга вроде как нельзя проинформировать детей.
Так что описаная ситуация невозможна.
Впрочем, я могу ошибаться, не проверял.

Вообще, что касается событий, я бы сказал, что это штука довольно мощная, однако подходить к использованию событий надо с умом и осторожностью.
Теоретически, все вызовы методов можно заменить событиями, однако этого никто не делает, поскольку это усложняет восприятие логики приложения.
Соответственно есть некая грань, которую нужно довольно четко понимать и думать, а стоит ли использовать именно событие.

Бабблинг работает от ребенка к родителю, да.
Что касается вызовов методов, то я по своему опыту могу сказать, что у меня прямые вызовы методов составляют где-то процентов 30 от всех…

terbooter, не очень понял твой вопрос.

terbooter 05.03.2008 09:19

Если коротко, то:
Существует ли поток событий если объект генерит событие с помощью
dispatchEvent

etc 05.03.2008 09:22

Цитата:

Сообщение от terbooter
Если коротко, то:
Существует ли поток событий если объект генерит событие с помощью
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);
}


etc 05.03.2008 09:32

(кастомный ивент мне было лень писать):
Код:

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));

Это же волшебно! Теперь не буду париться и для каждого блока контроллеров весить листенер. Все листенеры буду весить прямо на сцену.

etc 05.03.2008 09:55

Цитата:

Сообщение от terbooter
Все листенеры буду весить прямо на сцену.

Очень опрометчивое решение.

Iv 05.03.2008 14:00

Прям копи-пастом:
Для передачи событий из View (MVC) удобно использовать bubbling в сочетании со stopPropagation() там, где не требуется дальнейшее всплытие события.
В итоге все события View отлавливаются в Main и далее перенаправляются куда требуется.

toFlash 21.03.2008 11:52

Цитата:

Сообщение от Iv
Прям копи-пастом:
Для передачи событий из View (MVC) удобно использовать bubbling в сочетании со stopPropagation() там, где не требуется дальнейшее всплытие события.
В итоге все события View отлавливаются в Main и далее перенаправляются куда требуется.

Сори, хотел поинтересоваться, вот к примеру у меня есть класс меню, в нем класс итема, я вешаю генерацию события на итем - notify(), как теперь словить это событие на сцене??

Iv 21.03.2008 13:04

1 событие должно быть с баблингом
2 ты просто в рутовом классе пишешь addEventListener(MyMenuEvent.NOTIFY, onItemNotify);

примерно так


Часовой пояс GMT +4, время: 18:20.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.