Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   MovieClip: единый addEventListener (http://www.flasher.ru/forum/showthread.php?t=202841)

Fogflasher 14.08.2013 17:55

MovieClip: единый addEventListener
 
Вложений: 1
(Можно даже сказать: Единый Слушатель Событий Ада), лол.

Ок, всем привет.

Есть мувиклип Area1, в котором находятся три других мувиклипа: Krug1, Krug2, Krug3.
Все они залинкованы к одноименным классам через галочку Export to ActionScript.

Изначально стэйдж пустой. Класс Main заполняет его вот так:

Вложение 29909

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

Можно ли повесить только один слушатель на объект Area1, чтобы он, через родительские ссылки определял, какой кружок был нажат?

Я попытался сделать так:

Основной класс:
Код AS3:

package
{
 
        import flash.display.Sprite;
 
        public class Main extends Sprite
        {
                private var area1:Area1;
                private var eventHandler:EventHandler;
 
                public function Main()
                {
                        area1 = new Area1();
                        area1.x = 120;
                        area1.y = 150;
                        addChild(area1);
 
                        eventHandler = new EventHandler(area1);
 
                }
        }
 
}

Класс EventHandler:

Код AS3:

package
{
        import flash.display.MovieClip;
        import flash.events.*;
 
        public class EventHandler extends EventDispatcher
        {
 
                public function EventHandler(mc:MovieClip)
                {
                        mc.addEventListener(MouseEvent.CLICK, clickHandler);
                }
 
                private function clickHandler(e:Event)
                {
 
//                        if (e.currentTarget. ???)
//                        {
//                                trace("Krug1");
//                        }
//                        else if (e.currentTarget. ???)
//                        {
//                                trace("Krug2");
//                        }
//                        else if (e.currentTarget. ???)
//                        {
//                                trace("Krug3");
//                        }
 
 
 
                }
 
 
 
        }
 
 
}

Вот там где камменты, надо как-то условие задать, чтобы определялся кружок.

Но как это сделать?
Вроде бы нужно как-то e.currentTarget. использовать, но не понимаю как именно.

Некоторое соображение:
Изначально, у объектов на стэйдж нет <Instance names>.
Подозреваю что если бы они были, то было бы проще.
Тогда наверное прокатило бы что-то вроде:
Код AS3:

e.currentTarget.Area1_Instancename.Krug1_instancename

Но хотелось бы решить задачу без привязки к <Imstance name>, если это возможно конешно.

Hauts 14.08.2013 18:16

Код AS3:

if(e.currentTarget is Krug1){...}

Так поможет?

Deimos747 14.08.2013 20:13

Используйте #Event.target

AlexLucas 14.08.2013 20:59

currentTarget выдаст объект на который вы повесили слушатель, в данном случае Area1 (это прямоугольник в котором круги? ) а не круг.
target выдаст непосредственно IEventDispatcher который первым словил событие, если объект состоит из множества фигурок, то e.target будет не мувик Krug1, а какой-нибудь Shape694, и нужно будет проверять какой круг содержит этот шейп.
Можно создать класс Круг, там рисовать кружок, ловить и обрабатывать событие, в этом случае E.currentTarget будет именно тот Круг который нужен.

Цитата:

Изначально, у объектов на стэйдж нет <Instance names>.
Если объекту явно имя не задано, задаётся шаблонное имя (ИмяКласса672 например, цифра как-то вычисляется непонятно).

Dukobpa3 14.08.2013 21:15

Подписаться на все три клика одним листенером и смотреть event.currentTarget

Добавлено через 1 минуту
Цитата:

Код AS3:

class EventHandler extends EventDispatcher


А вот это слегка вырвиглазое решение.

Котейка 14.08.2013 23:42

Dukobpa3, путаетесь. Смотреть надо target :)

Dukobpa3 14.08.2013 23:45

Это вы, товарищ не поняли мой ответ.
Я сказал про три клика. На три объекта. Но листенер один.

Добавлено через 1 минуту
А про таргет вон выше ответили. Всякие шейпы фильтровать нафиг надо. Таргетом никогда не пользуюсь.

Котейка 14.08.2013 23:57

Dukobpa3, а вон оно что) Ну тогда да currentTarget.
Какой вариант удобнее и лучше зависит от задачи. В данном случае разницы нет.
В случае если объектов туева хуча, (н-р интерактивная карта) target будет предпочтительнее. :)

SvetozarPNZ 15.08.2013 09:57

В моей практике встречался подобный момент. Некоторые выдержки из кода:

Код AS3:

sp2.addChild(mass[it]);        // добавляем пазл в спрайт, где размещаются пазлы
sp2.addEventListener(MouseEvent.CLICK, toMoving, true); // добавляем прослушиватель спрайту с пазлами

Код AS3:

                public function toMoving(e):void {                        
                        var evDisp = e.target; // это экземпляр класса пазл
                        }
                }

Похоже ваша цель заключается в использовании параметра useCapture метода addEventListener Если не знакомы, то разбирайте фазы в потоке событий

Fogflasher 15.08.2013 11:24

Hauts, нет, так не помогло:
Код AS3:

                        if (e.currentTarget is Krug1)
                        {
                                trace("Krug1");
                        }

Иф не срабатывает, видимо потому что e.currentTarget = Area1, то есть квадрату-родителю.
Спасибо за указание на прием: is Object, я не сообразил что так можно.

Deimos747, AlexLucas, Котейка, благодарю за наводку на .target, сделал вот так:

Код AS3:

 
                        if (e.target is Krug1)
                        {
                                trace("Krug1");
                        }
                        else if (e.target is Krug2)
                        {
                                trace("Krug2");
                        }
                        else if (e.target is Krug3)
                        {
                                trace("Krug3");
                        }

Всё работает : ) Вроде никакие заморочки с шейпами и хитрыми номерами не нужны.
Или может быть они были бы нужны в каком-то более сложном случае? Например при сильной вложенности, или еще как.

Dukobpa3,
Код AS3:

А вот это слегка вырвиглазое решение.

А почему кстати? Я только недавно изучаю AS3.0, но по совету maincode расширял в данном случае не Sprite, а EventDispatcher.

Dukobpa3,
Цитата:

Подписаться на все три клика одним листенером и смотреть event.currentTarget
Не совсем понимаю, что вы имеете ввиду? То есть на каждый кружок повесить addEventListener, но который ссылается на единый обработчик?

SvetozarPNZ, мне просторе решение с target помогло.
Про useCapture не в курсе, возможно это нужно в более сложных случаях вложенности объектов? За ссылку спасибо.

KumoKairo 15.08.2013 11:45

Цитата:

А почему кстати? Я только недавно изучаю AS3.0, но по совету maincode расширял в данном случае не Sprite, а EventDispatcher.
Не заморачивайтесь пока такими вещами, на этапе обучения это только усложняет понимание принципов языка. Потом сами к этому придете.

Цитата:

Не совсем понимаю, что вы имеете ввиду? То есть на каждый кружок повесить addEventListener, но который ссылается на единый обработчик?
Три разных кнопки - один обработчик.
Если вешать слушатель на каждую кнопку в том элементе, где вы создаете кнопки, то .currentTarget покажет на конкретную кнопку.
В данном случае все таки лучше унаследоваться от Sprite чтобы не заморачиваться с двумя проблемами одновременно.

Код AS3:

...
private function setupButtons():void
{
        var button1:MyLittleButton = new MyLittleButton();
        var button2:MyLittleButton = new MyLittleButton();
        var button3:MyLittleButton = new MyLittleButton();
 
        addChild(button1);
        addChild(button2);
        addChild(button3);
 
        button1.addEventListener(MouseEvent.Click, genericClickListener);
        button2.addEventListener(MouseEvent.Click, genericClickListener);
        button3.addEventListener(MouseEvent.Click, genericClickListener);
}
 
private function genericClickListener(me:MouseEvent):void
{
        trace(me.currentTarget);
}
 
...


Dukobpa3 15.08.2013 11:51

Цитата:

То есть на каждый кружок повесить addEventListener, но который ссылается на единый обработчик?
Да.

Цитата:

по совету maincode расширял в данном случае не Sprite, а EventDispatcher.
Видимо совет касался чего-то другого. Выносить обработчик события куда-то отдельно от самого объекта достаточно нестандартное решение, требующее дополнительной мотивации так сделать.

Fogflasher 15.08.2013 14:45

KumoKairo, ваш пример несколько проще: у кнопок нет родительского объекта.
Если этот общий код попробовать реализовать применительно к моему примеру, то получается например так:

Код AS3:

package
{
 
        import flash.display.*;
        import flash.events.*;
 
        public class Main extends Sprite
        {
                private var area1:Area1 = new Area1();
                private var krug1:Krug1 = new Krug1();
                private var krug2:Krug2 = new Krug2();
                private var krug3:Krug3 = new Krug3();
 
                public function Main()
                {
                        area1.x = 120;
                        area1.y = 150;
                        addChild(area1);
 
                        krug1.addEventListener(MouseEvent.CLICK, genericClickListener);
                        krug2.addEventListener(MouseEvent.CLICK, genericClickListener);
                        krug3.addEventListener(MouseEvent.CLICK, genericClickListener);
 
                }
 
                private function genericClickListener(e:MouseEvent):void
                {
                        trace("e.currentTarget", e.currentTarget);
                }
 
        }
 
}

Однако он не работает, при нажатии на кнопки ничего не происходит (ошибок тоже нет).
Я пробовал заменить строки вот так:
Код AS3:

area1.krug1.addEventListener(MouseEvent.CLICK, genericClickListener);
area1.krug2.addEventListener(MouseEvent.CLICK, genericClickListener);
area1.krug3.addEventListener(MouseEvent.CLICK, genericClickListener);

Но в таком случае появляется одна ошибка:
Цитата:

TypeError: Error #1010: A term is undefined and has no properties.
at Main$iinit()
Dukobpa3, ну да это сделано по аналогии с примером из этого поста.
Вариант более оптимального кода - вынести обработчик в отдельный класс.

KumoKairo 15.08.2013 14:49

В первом примере переменные krug1 и т.д. никакого отношения к кнопкам в area1 не имеют) Во втором случае ошибка из-за того, что переменные krug1 и т.д. private (скорее всего) и их не видно вне area1.

Fogflasher 15.08.2013 15:05

KumoKairo, но тогда я что-то общую картинку не сложу до конца.

Цитата:

В первом примере переменные krug1 и т.д. никакого отношения к кнопкам в area1 не имеют)
Вот есть родитель-контейнер, и у него экземпляр area1, и вот есть один его ребёнок-внутренний-объект, и у него экземпляр: krug1.

И как же тогда обратится к этому ребёнку, если нет никакого отношения?

Цитата:

Во втором случае ошибка из-за того, что переменные krug1 и т.д. private (скорее всего) и их не видно вне area1.
Сделал все переменные public, но ошибка для формата:
Код AS3:

area1.krug1.addEventListener(MouseEvent.CLICK, genericClickListener);

осталась.

KumoKairo 15.08.2013 15:09

Покажите код Area1
Я не помню точно насчет нативных событий на флеш, но там можно определять, всплывает ли оно пузырьком по своим родителям или нет.

Zebestov 15.08.2013 15:22

Или я не вник особо, или у вас тут каша какая-то.
Вы что же это, рекомендуете вешать один слушатель на контейнер с кружочками и определять кружок по currentTarget?

Fogflasher 15.08.2013 15:41

KumoKairo, У него нет кода, это тупо квадрат (содержащий внутри кружки) созданный вручную в редакторе.
У него имя класса, как и у кружков, сделано посредством галочки Export to ActionScript.

Zebestov, ну вот выше в трэде мы выяснили что задачу легко решить через .target
А если попробовать сделать то же самое с currentTarget, то возникает вопрос, как это разрулить, с учетом того, что родительский объект содержит в себе объекты, на которых слушатели повешены.

AlexCooper 15.08.2013 16:10

Я бы повесил всё таки один addEventListener на общий контейнер. А для кругов установил свойство
Код AS3:

mouseChildren = false;

и использовал бы target.

Zebestov 15.08.2013 16:30

Цитата:

Сообщение от Fogflasher (Сообщение 1143857)
Zebestov, ну вот выше в трэде мы выяснили что задачу легко решить через .target

Что значит "легко"? Других вариантов просто нет. Предложение использовать currentTarget — ошибка.

Цитата:

Сообщение от Fogflasher (Сообщение 1143857)
А если попробовать сделать то же самое с currentTarget, то возникает вопрос, как это разрулить, с учетом того, что родительский объект содержит в себе объекты, на которых слушатели повешены.

Эти слушатели имеют отношение к решению данной задачи? Если да — пускай живут своей жизнью параллельно со слушателем на контейнере. Если нет — для чего они там?

Добавлено через 2 минуты
Цитата:

Сообщение от AlexCooper (Сообщение 1143859)
Я бы повесил всё таки один addEventListener на общий контейнер. А для кругов установил свойство
Код AS3:

mouseChildren = false;

и использовал бы target.

В таком случае target всегда указывал бы на контейнер, делая его таким же бесполезным, как и currentTarget.
Нужно как раз наоборот
Код AS3:

mouseEnabled = false;
mouseChildren = true;


Fogflasher 15.08.2013 17:30

Цитата:

Сообщение от Zebestov (Сообщение 1143861)
Эти слушатели имеют отношение к решению данной задачи? Если да — пускай живут своей жизнью параллельно со слушателем на контейнере. Если нет — для чего они там?

Нет, не имеют.
Это была попытка решить задачу по другому, мне достаточно .target-версии, другой вариант интересен чисто теоретически.

Насчет свойств, спасибо за наводку.
В хэлпе написано:

Цитата:

mouseEnabled
Specifies whether this object receives mouse, or other user input, messages. The default value is true, which means that by default any InteractiveObject instance that is on the display list receives mouse events or other user input events. If mouseEnabled is set to false, the instance does not receive any mouse events (or other user input events like keyboard events). Any children of this instance on the display list are not affected.
Цитата:

mouseChildren
Determines whether or not the children of the object are mouse, or user input device, enabled.
If an object is enabled, a user can interact with it by using a mouse or user input device. The default is true.

Для target-версии эти свойства для кругов не нужны, и так всё работает.
Но если все-таки повесить свойства на area1, то работает только вариант:
Код AS3:

                        area1.mouseEnabled = false;
                        area1.mouseChildren = true;


Для currentTarget-версии, попробовал такие комбинации:
Код AS3:

//---------- Variant 1a --------------------//
//                        krug1.mouseEnabled = false;
//                        krug2.mouseEnabled = false;
//                        krug3.mouseEnabled = false;
//                       
//                        krug1.mouseChildren = true;
//                        krug2.mouseChildren = true;
//                        krug3.mouseChildren = true;
 
//---------- Variant 1b --------------------//
//                        krug1.mouseEnabled = true;
//                        krug2.mouseEnabled = true;
//                        krug3.mouseEnabled = true;
//                       
//                        krug1.mouseChildren = false;
//                        krug2.mouseChildren = false;
//                        krug3.mouseChildren = false;
 
//----------- Variant 2a ---------------------//
 
//                        area1.mouseEnabled = true;
//                        area1.mouseChildren = false;
 
//----------- Variant 2b ---------------------//
//
//                        area1.mouseEnabled = false;
//                        area1.mouseChildren = true;
//-----------------------------------------//

Это не помогает, вешай слушаетль хоть на krug'и, хоть на area1.

Значит Zebestov прав, currentTarget-версия какбэ невозможна : )


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

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