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
|
原因
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日