サイトトップ

Director Flash 書籍 業務内容 プロフィール

Adobe Flash非公式テクニカルノート

DisplayObject.removedとDisplayObject.removedFromStageイベントの違い

ID: FN1101002 Product: Flash CS3 and above Platform: All Version: 9 and above/ActionScript 3.0

DisplayObject.removed(定数Event.REMOVED)とDisplayObject.removedFromStage(定数Event.REMOVED_FROM_STAGE)イベントは、いずれもインスタンスが「表示リストから削除されようとしているとき」に起こります(表001)。しかし、その細かな違いがわかりにくいです。

表001■[ヘルプ]のDisplayObject.removedとDisplayObject.removedFromStageイベントの説明
DisplayObjectクラスのイベント 説明
removed 表示オブジェクトが表示リストから削除されようとしているときに送出されます。
removedFromStage 表示オブジェクトが、直接、または表示オブジェクトを含むサブツリーの削除により、表示リストから削除されようとしているときに送出されます。

01 表示リストから削除されるイベントはどのようなときに起こるか
まずは、DisplayObject.removedDisplayObject.removedFromStageイベントがどのようなときに起こるのか、簡単なスクリプトで試してみましょう(スクリプト001)。親子にするふたつのSpriteインスタンスをつくり、親インスタンス(mySprite)はメインタイムライン、子インスタンス(myChild)は親インスタンスの表示リストに納めます(第1〜4行目)。そして、子インスタンスにDisplayObject.removedDisplayObject.removedFromStageイベントのリスナー関数(onRemoved())を加えます(第5〜6行目)。そのうえで、子インスタンスを親インスタンスの表示リストから除いてみます(第7行目)。

スクリプト001■子インスタンスにイベントリスナーを加えてみる
    // フレームアクション: メインタイムライン
  1. var mySprite:Sprite = new Sprite();
  2. var myChild:Sprite = new Sprite();
  3. addChild(mySprite);
  4. mySprite.addChild(myChild);
  5. // 子インスタンスにイベントリスナー登録
  6. myChild.addEventListener(Event.REMOVED, onRemoved);
  7. myChild.addEventListener(Event.REMOVED_FROM_STAGE, onRemoved);
  8. mySprite.removeChild(myChild);   // 子インスタンスを表示リストから除く
  9. function onRemoved(eventObject:Event):void {
  10.   trace(eventObject.type);
  11. }

[ムービープレビュー]を確かめると、ふたつのイベントリスナーがともに呼出されます。つまり、子インスタンスに、DisplayObject.removedDisplayObject.removedFromStageイベントがともに発生したことを示します。

removed
removedFromStage

では、スクリプト001の第3行目をコメントアウトしてみます。つまり、子インスタンスは親インスタンスの表示リストに納められるものの(第4行目)、親インスタンスには親がなく、どの表示リストにも属しません。

  1. // addChild(mySprite);   // コメントアウト
  2. mySprite.addChild(myChild);
  1. mySprite.removeChild(myChild); // 子インスタンスを表示リストから除く

[ムービープレビュー]を試すと、子インスタンスのDisplayObject.removedイベントだけが起こります。もともとStageオブジェクトを頂点とした表示リストの階層(ツリー)に加わっていなかったので、DisplayObject.removedFromStageイベントは発生しないのです。

removed

さて、コメントアウトしたスクリプト001の第3行目は、もとに戻して有効にします。つまり、親インスタンスはメインタイムラインの表示リストに加わります。ただ今度は、第7行目をコメントアウトして、替わりに親インスタンスをメインタイムラインの表示リストから除いてしまいます。

  1. addChild(mySprite);
  2. mySprite.addChild(myChild);
  1. // mySprite.removeChild(myChild); // 以下に変更
    removeChild(mySprite);   // 親インスタンスを表示リストから除く

[ムービープレビュー]すると、子インスタンスのDisplayObject.removedFromStageイベントが起こります。子インスタンス自身は親インスタンスの表示リストに納まったままです。ですから、DisplayObject.removedイベントは生じません。けれど、親インスタンスがStageオブジェクトを頂点とした表示リストから除いたので、その結果子インスタンスもその階層(ツリー)から外れることになるからです。

removedFromStage

このように、DisplayObject.removedイベントは、インスタンスが表示リストから除かれたときに起こります。それに対して、DisplayObject.removedFromStageイベントは、Stageオブジェクトの表示リストの階層(ツリー)から外れたときに発生するということです[*1]

[*1] DisplayObjectインスタンスをステージに表示するには、必ずStageオブジェクトを頂点とする表示リストの階層(ツリー)に加わらなければなりません。よって、DisplayObject.removedFromStageイベントは、ステージに表示されなくなったことを示すといえます。


02 表示リストから削除されるイベントが誰に送られるか
前掲スクリプト001を少し書替えましょう。DisplayObject.removedDisplayObject.removedFromStageイベントのリスナーを子インスタンスでなく、親インスタンスに加えます(スクリプト002第5〜6行目)。けれど、表示リストから削除するのは、子インスタンスのまま変えません(第7行目)。

スクリプト002■親インスタンスにイベントリスナーを加えてみる
    // フレームアクション: メインタイムライン
  1. var mySprite:Sprite = new Sprite();
  2. var myChild:Sprite = new Sprite();
  3. addChild(mySprite);
  4. mySprite.addChild(myChild);
  5. // 親インスタンスにイベントリスナー登録
  6. mySprite.addEventListener(Event.REMOVED, onRemoved);
  7. mySprite.addEventListener(Event.REMOVED_FROM_STAGE, onRemoved);
  8. mySprite.removeChild(myChild);   // 子インスタンスを表示リストから除く
  9. function onRemoved(eventObject:Event):void {
  10.   trace(eventObject.type);
  11. }

[ムービープレビュー]を見ると、親インスタンスのDisplayObject.removedイベントが起こるようです。しかし、親インスタンスは、メインタイムラインの表示リストから除いていません。では、なぜイベントを受取るのでしょう。

removed

[ヘルプ]には、ふたつのイベントそれぞれで送られるEventオブジェクトのプロパティを表にして掲げています。これらのEvent.bubblesプロパティを見ると、イベントDisplayObject.removedではtrueDisplayObject.removedFromStagefalseとなっています(表002)。

表002■DisplayObject.removedとDisplayObject.removedFromStageイベントのEvent.bubblesプロパティ
DisplayObjectクラスのイベント Event.bubblesプロパティ
removed true
removedFromStage false

Event.bubblesプロパティがtrueというのは、多くのマウスイベントのようにイベントオブジェクトが表示リストの親インスタンスに送られることを意味します。そのため、子インスタンスが表示リストから除かれても、親インスタンスのリスナー関数がイベントを受取れるのです。もし、そのインスタンス自身が表示リストから削除されたときだけ処理を行いたいときは、Event.targetプロパティを調べればよいでしょう[*2][*3]

[*2] 前掲スクリプト002に手を加えて、リスナー関数(onRemoved())内のtrace()関数に引数としてEvent.targetEvent.currentTargetプロパティを加えれば確かめられます(第9行目)。なお、親子のSpriteインスタンスが区別できるように、それぞれにDisplayObject.nameプロパティを設定しておきます。

  1. var mySprite:Sprite = new Sprite();
  2. var myChild:Sprite = new Sprite();
    // DisplayObject.nameプロパティを追加
    mySprite.name = "myself";
    myChild.name = "child";
  3. addChild(mySprite);
  4. mySprite.addChild(myChild);
  5. mySprite.addEventListener(Event.REMOVED, onRemoved);
  6. mySprite.addEventListener(Event.REMOVED_FROM_STAGE, onRemoved);
  7. mySprite.removeChild(myChild);
  8. function onRemoved(eventObject:Event):void {
  9.   // Event.targetとEvent.currentTargetプロパティの値を追加
  10.   trace(eventObject.type,
        eventObject.target.name,
        eventObject.currentTarget.name);
  11. }

[出力]結果はつぎのとおりです。子インスタンスに発生したDisplayObject.removedイベント(Event.targetプロパティ)が、親インスタンスのイベントリスナーに送られて処理された(Event.currentTargetプロパティ)ことを示します。

removed child myself

[*3] これに対して、DisplayObject.removedFromStageイベントは、親インスタンスからイベントオブジェクトを受取る訳ではありません。自らが属する表示リストのツリーが、Stageオブジェクトを頂点とする表示リストから外れれば、そのインスタンスにイベントが直接送られます。つまり、Event.targetEvent.currentTargetプロパティはつねに同じです。



作成者: 野中文雄
作成日: 2011年1月14日


Copyright © 2001-2011 Fumio Nonaka.  All rights reserved.