AS3で親(parent)MCのremoveChild→子MCのイベントリスナーごとremoveEventListenerで削除
FlashのActionScript3.0(AS3)は相変わらずムズカシイです...
リンケージ(ってAS3でリンケージはナイんですが)使ってaddChildしまくってると、MovieClip(MC)同士の親子関係がかなり複雑になってきます。
親MCにaddChildした子MCにまたaddChildして孫MCを生成...みたいなカンジでコーディングしていたのですが、子MCにも孫MCにもaddEventListenerでガシガシイベントリスナーを設定してしまいまして、いざ全部removeChildで削除しようとするとイベントリスナーがキチンとremoveEventListenerされてないってんでエラー頻発!
って自分で書いててもナニ言ってんだってカンジです。
一気にスッキリイベントリスナーまで削除できないものかと悩みまして、またもやGoogle先生の力を借りて先人の知恵を拝借しました!
子MCのイベントリスナーをremoveする
そんなこんなで最初に見つけたのが子MCのイベントリスナーをremoveEventListenerする方法。[AS3]子swfのイベントリスナーをremoveしたいよ | blog.hereticsintheworld子SWFに以下のイベントリスナーを追加。
[as]this.addEventListener(Event.REMOVED_FROM_STAGE,removeFunc);[/as]
[as]function removeFunc (e:Event):void {
removeEventListener(Event.ENTER_FRAME,onEnterFunc);
}[/as]
こうすると親swfで子swfのLoaderオブジェクトをremoveChildしたときにイベント発動。
初めて知ったw
もっとステキな方法があるはずだよね。。。
おぉ!なるほどREMOVED_FROM_STAGEなんて便利なイベントがあるんですね!!
いやちょっと待ってこれ親(parent)MCがremoveChildで削除されてもイベント発生させられるんじゃないですか?!
親MCをremoveChild→子MCのイベントリスナーごとremoveEventListenerで削除
という事で親MCをremoveChildで削除すると、全部の子MCのイベントリスナーごとremoveEventListenerで削除しまうActionScriptです。例えばステージ(Stage)上に配置した親MCのタイムラインにこんなASを書いてみます。
stage.addEventListener(Event.RESIZE,stageResize);
MovieClip(root).deleteBtn.addEventListener(MouseEvent.MOUSE_DOWN,parentDelete);
//ステージサイズ変更
function stageResize(evt:Event):void {
this.width = stage.stageWidth;
}
//親MC削除
function parentDelete(event:MouseEvent):void {
stage.removeEventListener(Event.RESIZE,stageResize);
MovieClip(root).deleteBtn.removeEventListener(MouseEvent.MOUSE_DOWN,parentDelete);
parent.removeChild(this);
}
同じくステージに配置したdeleteBtnボタンを押す(MOUSE_DOWN)とparentDelete関数が発動して親MC自身が削除されます。
ちなみにrootを「MovieClip(root)」という風に書くとインスタンスとして扱えるみたいです。これでステージ上の他のMCからのイベントリスナーも取り出せます。
イベントリスナーをMOUSE_DOWNにしてるのはボタンを押した時に削除を実行して、ボタンを離した(MOUSE_UP)ときに別のMCをリンケージする関数を呼び出す二重構造でやりたかっただけなので、普通にCLICKで設定しても問題ナイです。
parentDelete関数をparentDelete関数自身でremoveEventListenerして無効化。親MC自身が削除されるのでイベントリスナーもガベージコレクションにしてメモリを空けた方がいいのかな~と。
いずれにしても複雑化した関数もスッキリ整理できるので便利な書き方だと思います。
removeChildは通常は子MCを削除するために使いますが、「parent.removeChild(this)」と表記する事で自分自身を削除する事が可能です。
次に子MCにこんなASを記述。
this.addEventListener(MouseEvent.CLICK,mouseClick);
parent.addEventListener(Event.REMOVED_FROM_STAGE,childDelete);
//マウスクリック
function mouseClick(event:MouseEvent):void {
trace(this.name);
}
//子MC削除
function childDelete(evt:Event):void {
this.removeEventListener(MouseEvent.CLICK,mouseClick);
parent.removeEventListener(Event.REMOVED_FROM_STAGE,childDelete);
parent.removeChild(this);
}
親MCがremoveChildされるとREMOVED_FROM_STAGEのイベントがトリガーになって、自動的に子MC自身がイベントリスナーごと自分を削除してしまいます。
親子関係にあるMCを削除する場合、forとnumChildrenで全部の子MCを削除する方法もあるのでしょうが、これだと子MCの中のイベントリスナーまでは無効化できないので、ここにあげた子MC自身が自発的に削除される方法のほうが取回しは楽かと思います。
親MCのstageResize関数と子MCのmouseClick関数に反応するイベントリスナーみたいに、親MCや子MC自身にたくさんイベントリスナーが設定されていても、削除をするときに一緒にremoveEventListenerすればイイだけなのですごく楽チンです。
いや~大した事ないコーディングなんですが、実際ここまでたどり着くのは大変でしたw
ちなみに記事の頭に入れた画像はFlash CS3の初期画面です。
以前からActionScriptのコーディングがしにくいウィンドウ構成だな~と思っていたのですが、思い切って配置を変えてみました。
解像度の高いディスプレイを使っているのならアクションのウィンドウを大きく取れるこの配置の方がかなり楽ですよ♪
