Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Как правильно расширить класс? (http://www.flasher.ru/forum/showthread.php?t=215556)

djken 15.05.2018 18:17

Цитата:

Ну, во-первых писать типы событий хардкодом типа "COMPLETE" - это моветон.
Согласен. Привык так по-быстрому писать.. Надо будет на досуге разобраться как все же правильно. Константу объявлять в этом же классе или лучше создавать отдельный класс под события?

Цитата:

для события complete есть штатная константа Event.COMPLETE, даже свою объявлять не надо
Event.COMPLETE конечно знаю - использую, когда подписываюсь. Но не знал, что его же можно использовать и в кастомных.. Т.е. как я понял ты говоришь об этом - вместо
Код AS3:

dispatchEvent(new Event('COMPLETE'));

писать
Код AS3:

dispatchEvent(Event.COMPLETE);

А еще лучше перенаправлять
Код AS3:

dispatchEvent(e);

Значит оставлю override, раз это лучше. Буду знать. Снкс!

caseyryan 15.05.2018 20:54

Цитата:

Event.COMPLETE конечно знаю - использую, когда подписываюсь. Но не знал, что его же можно использовать и в кастомных.. Т.е. как я понял ты говоришь об этом - вместо
Код AS3:

dispatchEvent(new Event('COMPLETE'));

писать
Код AS3:

dispatchEvent(Event.COMPLETE);


Нет. Event.COMPLETE - это всего лишь строка. Это не событие. Она лишь указывается для задания типа событию. Поэтому писать надо так:
Код AS3:

dispatchEvent(new Event(Event.COMPLETE));


djken 16.05.2018 01:50

caseyryan, огромнейшее спасибо за помощь!

djken 24.05.2018 11:53

Наконец-то сел почитать, чтобы разобраться с Событиями досканально - многое прояснил для себя.
Но есть момент, в котором не знаю как правильно поступить: как раз столкнулся на моем примере, когда по совету от caseyryan стал не создавать свое новое событие, а передиспатчивать существующее - dispatchEvent(e).

Мне нужно ловить событие клика по спрайту _box, который внутри класса ImageBox.

Код AS3:

public class ImageBox extends Sprite
{
    private var _box:Sprite; // в этом спрайте рисуется бэкграунд и грузится картинка
    private var _cb:CheckBox; // чекбокс
 
    public function ImageBox()
    {
          _box = new Sprite();
          _box.addEventListener(MouseEvent.CLICK, onClickHandler);
          addChild(_box);
 
          _cb = new CheckBox();
          addChild(_cb);
    }
 
    private function onClickHandler(e:MouseEvent):void
    {
          dispatchEvent(e);
    }
}

Код AS3:

_imageBox = new ImageBox();
_imageBox.addEventListener(MouseEvent.CLICK, onClick);
addChild(_imageBox);
 
private function onClick(e:MouseEvent):void
{
    trace(e.target); // выводит [object ImageBox] и [object Sprite]
}

В итоге обработчик onClick срабатывает два раза.
Как я понимаю:
ImageBox имеет событие click, унаследовав от Sprite. И _box тоже. Подписавшись на событие click у _imageBox - из-за цепочки событий в иерархии отображаемых объектов на фазе захвата происходит диспатч сначала у предка [object ImageBox], а потом и у получателя [object Sprite].
Верно ли понимаю?

Вопрос: мне не нужно чтобы onClick срабатывал дважды, т.к. в нем будут производиться какие-либо действия дважды.. Вижу два выхода: 1) в обработчике проверять от кого пришло событие и только после этого выполнять дальнейшие действия. 2) либо все таки в onClickHandler диспатчить свое событие.

Подскажите пожалуйста.

undefined 24.05.2018 15:33

dispatchEvent диспатчит клон события,поэтому перед посылкой оригинальное событие надо остановить через stopImmediatePropogation.

Wolsh 24.05.2018 17:16

От задачи же зависит..
Если вам надо событие клика по КАРТИНКЕ, но к самой картинке доступа нет и добавить ей слушатель нельзя, то придется диспатчить от имени контейнера и тогда да, лучше использовать кастомное событие. То есть обычный Event, но со "своим" строковым типом, который можно объявить константой в классе ImageBox, пусть будет ImageBox.CLICK_IMAGE.
Код AS3:

public class ImageBox extends Sprite
{
        static public const CLICK_IMAGE:String = "clickImage";
        private var _box:Sprite; // в этом спрайте рисуется бэкграунд и грузится картинка
        private var _cb:CheckBox; // чекбокс
 
        public function ImageBox()
        {
                _box = new Sprite();
                _box.addEventListener(MouseEvent.CLICK, onClickHandler);
                addChild(_box);
        }
 
        private function onClickHandler(e:MouseEvent):void
        {
                dispatchEvent(new Event(CLICK_IMAGE));
        }
}

Код AS3:

_imageBox = new ImageBox();
_imageBox.addEventListener(ImageBox.CLICK_IMAGE, onClickImage);
addChild(_imageBox);
 
private function onClickImage(e:Event):void
{
        trace(e.target); // выводит [object ImageBox]
}


djken 24.05.2018 17:46

Цитата:

Если вам надо событие клика по КАРТИНКЕ, но к самой картинке доступа нет и добавить ей слушатель нельзя
Wolsh, т.е. правильнее _box сделать публичной, чтобы можно было подписываться напрямую?
Код AS3:

_imageBox._box.addEventListener(MouseEvent.CLICK, onClick)

вернее через акцессор
Код AS3:

public function get box():Sprite
{
    return _box;
}

Код AS3:

_imageBox.box.addEventListener(MouseEvent.CLICK, onClick);

или все таки диспатчить свое событие clickImage?


undefined, попробовал stopImmediatePropogation, работает. Но не совсем понимаю, что значит dispatchEvent диспатчит клон?
В справке Adobe ничего не нашел про stopImmediatePropogation. Упоминается вскользь...
Цитата:

Прослушиватель события может изменить это поведение, вызвав метод preventDefault(). Также можно сделать текущий прослушиватель событий последним для обработки события путем вызова метода stopPropogation() или stopImmediatePropogation().

undefined 24.05.2018 18:00

Цитата:

Но не совсем понимаю, что значит dispatchEvent диспатчит клон?
Это значит,что когда ты пишешь
Код AS3:

dispatchEvent(e);

Рассылается не само событие e,а то,что вернет e.clone()(клон события).А само событие e продолжит свое путешествие по дисплейлисту,поэтому у тебя лисенер и срабатывал 2 раза т.к. ловил оригинальный ивент и клон.

djken 24.05.2018 18:05

undefined, теперь понял! Огромное спасибо за разъяснение!

Wolsh 24.05.2018 20:46

Цитата:

В справке Adobe ничего не нашел про stopImmediatePropogation. Упоминается вскользь...
Это методы класса Event, там и надо искать))
Цитата:

Wolsh, т.е. правильнее _box сделать публичной, чтобы можно было подписываться напрямую?
А он тебе нужен еще для чего-то "снаружи" ImageBoxa? У тебя возникала когда-нибудь неразбериха при подписке на Лоадер, что нужно лезть в какой-то Loader.loaderInfo? Меня это всегда раздражало. Тебе ведь, положа руку на сердце, нафиг там не нужен MouseEvent со всеми его 100500 данными на борту, где только координаты мышки в момент клика представлены аж шестью свойствами, а еще данные о зажатых/незажатых клавишах альт и шифт, и тому подобные подробности? Если тебя интересует только факт клика по картинке, то я бы только его и диспатчил. Тем более, что этот ImageBox, как я понимаю, будет и другие события посылать — о выборе в чекбоксе например, что-то еще; он часть системы, модуль, со своим поведением и характером, а картинка просто картинка, нет смысла ее публиковать на все приложение, она не выполняет функций — не имеет поведения, даже своего класса не имеет, и знать о ней никому не надо. Не ради клика точно.


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

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