Форум 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=143919)

MrXoT 29.08.2010 18:47

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

Main.as

Код AS3:

package {
        import flash.display.*;
        import flash.events.*;
        import test.*;
 
        public class main extends MovieClip {
                public function main(){
 
                        var mc:MovieClip = new createMovieClip(this, "mc1");
                        mc.graphics.beginFill(0xFFCC00);
                        mc.graphics.drawCircle(40, 40, 40);
 
                        mc.enterFrame(function(){
                                trace("test");                                       
                        });
                }
        }
}

и в папке test.

createMovieClip.as

Код AS3:

package test {
        import flash.display.MovieClip;
        import flash.events.*;
 
        public class createMovieClip extends MovieClip {
                public var parents:Array = new Array();
 
                public function createMovieClip(parentObj:Object, instantName:String){
                        this.name = instantName;
                        parentObj.addChild(this);
 
                        trace(this.parent);
                }
 
                public function enterFrame(func:Function){
                        this.addEventListener(Event.ENTER_FRAME, func);
                }
 
                public function removeEnterFrame(){
                        //this.removeEventListener(Event.ENTER_FRAME, func);
                }
        }
}

Вопрос, как в этом случае удалить событие ENTER_FRAME ?
Если я что то делаю не правильно, обьясните почему и желательно пример.
Заранее спасибо.

in4core 29.08.2010 19:23

Код AS3:

this.removeEventListener(Event.ENTER_FRAME, func);

в классе
Код AS3:

mc.removeEnterFrame(func);

в super классе

Вроде так

Psycho Tiger 29.08.2010 19:39

Поехали.
Код AS3:

public class main extends MovieClip {

Классы пишутся с большой буквы. Я на 100% уверен, что MovieClip Вам нафиг не нужен. Я вообще слабо представляю рядовую ситуацию, в которой надо наследоваться сразу от MovieClip. Программно Вы кадры не добавите. Наследуйтесь от Sprite`а.

Код AS3:

var mc:MovieClip = new createMovieClip(this, "mc1");

Это здорово, передавать parentObj. Только забудьте этот подход, раз и навсегда. К тому же, дело Вы имеете с DisplayObject`ами - а у них есть геттер parent.
Код AS3:

mc.enterFrame(function(){
                                trace("test");                                       
                        });

Это полнейшая глупость что Вы написали. Замыкание (это функция в методе) - это очень и очень плохо. Поищите на форуме, много раз объяснялось. Например, из за этого замыкания Вы никак не отпишитесь от этого метода не имея прямой ссылки на него вне его тела. Более того, гораздо проще написать
Код AS3:

mc.addEventListener(Event.ENTER_FRAME, yourFunction);

для достижения такого-же эффекта. Зачем Вы ради этого создали новый метод?
Код AS3:

this.name = instantName;

Ну, ничего плохого в этом нету, но name Вам нафиг не нужен. Это осталось в прошлых версиях языка - сейчас используются ссылки. Всё стало серьезно, долой детские игрушки, такие как "имя". Пффф~~ Оно может пригодится, наверно, только для метода getChildByName - а имея ссылку на ребёнка (а Вы её имеете) - это ненужно.

Теперь обрисую что происходит:
Замыканием Вы создали новую функцию. Совсем новую, о которой никто ничего не знает, кроме её самой. В АС3 можно подписаться и отписаться на сколько угодно событий сколькими угодно обработчиками, но нужно точно знать - что отписываем, а что нет.
О функции
Код AS3:

function(){
                                trace("test");                                       
                        }

знают два места: это тело функции и аргумент метода enterFrame, в который передали ссылку на эту бедофункцию. Аргумент "умирает" после конца тела функции, если его нигде не запомнить - в итоге потерялась вторая и последняя ссылка на эту функцию. В итоге - никак.
Нет, ну конечно можно взять и сохранить в переменную поля класса эту самую func, только вот нафига?
Код:

package {
        import flash.display.*;
        import flash.events.*;
        import test.*;
 
        public class Main extends Sprite {
                public function Main(){
 
                        var mc:MovieClip = new createMovieClip(this, "mc1");
                        mc.graphics.beginFill(0xFFCC00);
                        mc.graphics.drawCircle(40, 40, 40);
mc.graphics.endFill();
                        mc.addEventListener(Event.ENTER_FRAME, onEnterFrame);
//а сейчас отпишемся.
mc.removeEventListener(Event.ENTER_FRAME, onEnterFrame);
//отписались, не успев подписаться. Как всё просто без замыканий то!
                }
private function onEnterFrame(event:Event):void{
trace("Test!");
}
        }
}

UPD: сори за табуляцию, в браузере не работает, открывать редактор лень)

MrXoT 29.08.2010 19:47

Psycho Tiger
Спасибо за обьяснения, я понял свои ошибки, попробую исправиться и найти другой подход.

Чтоб не отходить от темы, а можно ли запустить функцию в событии при этом задав аргументы, что то вроде такого.

Код AS3:

mc.addEventListener(Event.ENTER_FRAME, onEnterFrame(param1, param2));
private function onEnterFrame(param1, param2){
  trace(param1);
}


Psycho Tiger 29.08.2010 20:23

Нет, вот так нельзя. Можно, но там плохо это делать - это дело нечитабельно и через одно место.

В обязательном аргументе в метод передается экземпляр класса Event - он содержит свойства currentTarget и target, я думаю их будет заглаза.
Код AS3:

mc.num=5; //предварительно нужно создать поле num у класса, чьим экземпляром является mc
mc.addEventListener(Event.ENTER_FRAME, onEnterFrame);
mc2.num=2;
mc2.addEventListener(Event.ENTER_FRAME, onEnterFrame);
private function onEnterFrame(event:Event){
  var mc:SomeClass=event.target as SomeClass; //получили ссылку на того, кто подписан. То есть этот обработчик вызовется 2 раза и event.target будет сначала mc, потом mc2
trace(mc.num); //выводится 1 или 2
}


Hidest 30.08.2010 01:37

Пару раз в неделю возникают темы по типу "Как передать параметр в слушателя"... Вагон и маленькая телега вариантов, а так же всех "за" и "против" разных вариантов там имеется, поиск вам использовать надо!


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

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