サイトトップ

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

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

PopUpManager.createPopUp()で_root以外にインスタンスが作成できない

ID: FN0604003 Product: Flash

Platform: Windows
Version: MX 2004 and 8

問題
PopUpManager.createPopUp()メソッドは、第1引数でインスタンスを作成する親タイムラインが指定できます。ところが、第1引数にどのMovieClipのパスを指定しても、つねに_root直下にインスタンスが生成されてしまいます[*1]。

たとえば、メインタイムラインにMovieClipインスタンスを作成して、その参照をPopUpManager.createPopUp()メソッドの第1引数に渡しても、新規インスタンスはメインタイムライン_level0の下に作成されます(スクリプト001)。

スクリプト001■PopUpManager.createPopUp()はつねに_rootにインスタンスを作成

// タイムライン: _root
// フレームアクション
import mx.managers.PopUpManager;
import mx.containers.Window;
var _mc:MovieClip = this.createEmptyMovieClip("parent_mc", 1);
var win:Window = Window(PopUpManager.createPopUp(_mc, Window, true));
trace(win);   // 出力: _level0.depthChild0


[*1] LiveDocs Flash MX 2004「PopUpManager.createPopUp()」のコメントをご参照ください。

原因
PopUpManager.createPopUp()メソッドに、問題があります。メソッドに渡した第1引数のパスを_rootまで遡り、そこに新規インスタンスを作成する処理が記述されています[*2]。

この処理は、ドキュメントと齟齬があることは明らかです。しかし、処理の目的が明確でないため、問題はこの動作にあるのか、ドキュメントの記述が誤っているのかははっきりしません。

[*2] PopUpManagerクラスのクラス(静的)メソッドcreatePopUp()は、以下のように定義されています(スクリプト002)。

第1引数として渡したMovieClipの参照は、whileステートメントにより自身の_parentプロパティの値(タイムライン)に書替えられ、そのループ処理は値が_rootにたどり着くまで繰返されます。そして、_rootまで遡ったその参照をターゲットにして、新規インスタンスがDepthManager.createClassChildAtDepth()メソッドを用いて作成されます。

スクリプト002■PopUpManager.createPopUp()メソッド(抜粋)

class mx.managers.PopUpManager
{
  // ...[中略]...
  static function createPopUp(parent:MovieClip, className:Object, modal:Boolean, initobj:Object, broadcastOutsideEvents:Boolean):MovieClip
  {
    // ...[中略]...
    // find the top level parent

    var localRoot = parent._root;
    if (localRoot == undefined) localRoot = _root;
    while (parent != localRoot)
    {
      parent = parent._parent;
    }

    initobj.popUp = true;
    var o:MovieClip = parent.createClassChildAtDepth(className, (broadcastOutsideEvents || modal) ? DepthManager.kTopmost : DepthManager.kTop, initobj);

対処法
MovieClip._lockrootプロパティを設定して、指定したタイムラインを遡る処理は回避することができます。

第1引数に指定するMovieClipインスタンスについて、予めそのMovieClip._lockrootプロパティをtrueに設定します。すると、PopUpManager.createPopUp()メソッドの処理中に、第1引数の参照が_rootとして認識されますので、タイムラインを遡る処理が行われません。したがって、指定したタイムラインに、インスタンスを正しく作成することができます(スクリプト003)[*3][*4]。

スクリプト003■MovieClip._lockrootでタイムラインを遡らないように設定

// タイムライン: _root
// フレームアクション
import mx.managers.PopUpManager;
import mx.containers.Window;
var _mc:MovieClip = this.createEmptyMovieClip("parent_mc", 1);
_mc._lockroot = true;
var win:Window = Window(PopUpManager.createPopUp(_mc, Window, true));
trace(win);   // 出力: _level0.parent_mc.depthChild0
_mc._lockroot = false;   // プロパティの設定を戻す
/* _lockroot設定の効果テスト用[*3]
_mc.onMouseDown = function() {
  trace(this._root);
};
*/


[*3] PopUpManager.createPopUp()メソッドの呼出し後には、必ず第1引数に渡したMovieClip._lockrootプロパティをfalseに戻してください。そうしないと、今度はそのタイムラインから、_rootを起点にした絶対パスが正しく指定できなくなります。

上記スクリプト003で、コメントアウトされている「_lockroot設定の効果テスト用」のイベントハンドラメソッドを有効にして、ステージ上をクリックしてみてください。MovieClip._lockrootの値を戻した場合と戻さない場合とで、[出力]パネルに表示されるパスにより_root参照の違いを確認することができます。

[*4] この問題については、Flashcodersのスレッド「[Flashcoders] v2 components, broken library issue」で議論されています。

_____

作成者: 野中文雄
作成日: 2006年4月11日
ドラフト作成: 2006年4月7日


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