2010年07月19日

コンテキストメニューを変更する

覚書

ステージを右クリックしたときのコンテキストメニューの変更方法


AS2.0に慣れすぎたのか、AS3.0は「なんでこんなところまで変更するのよ」って言いたくなるくらい扱い難い。。。

さてと、困ったもんでstageのプロパティは読み取り専用で、任意の設定ができないんですって。

参考URL : http://livedocs.adobe.com/flash/9.0_jp/ActionScriptLangRefV3/flash/display/Stage.html


でも、設定したいのよ!ってことでその方法をメモ。

メインタイムラインに記述
//コンテキストメニュ−作成
var cm = new ContextMenu();
//とりあえず全部を隠しておいて
cm.hideBuiltInItems();
//表示したい項目だけ設定
cm.builtInItems.quality = true;

// コンテキストメニューを関連付ける
this.contextMenu = cm;


って書いてみると、2.0とさほど変わりないんだけど、登録の部分
ターゲットがstageだったのをthisに変更になる。
仕組みがあまり解ってないんだが、ConextMenuクラスってのがあって、それを使う。

flash.ui.ContextMenu

参考URL:http://livedocs.adobe.com/flash/9.0_jp/ActionScriptLangRefV3/flash/ui/ContextMenu.html
ContextMenu オブジェクトは、特定のボタンやムービークリップ、テキストフィールドオブジェクト、またはムービー全体に関連付けることができます。この場合は、Button クラス、MovieClip クラス、TextField クラスの menu プロパティを使用します。menu プロパティの詳細については、Button.menu、MovieClip.menu、および TextField.menu を参照してください。

なんか、この説明見てるとステージにも適用されてもよさそうなのにね。


まずは、ここのContextMenu()メソッドで、ContextMenuオブジェクトを作成。
ビルトインアイテムの設定は、ContextMenuBuildInItemsクラスのプロパティを使う。
参考URL : http://livedocs.adobe.com/flash/9.0_jp/ActionScriptLangRefV3/flash/ui/ContextMenuBuiltInItems.html

設定をしたら、最後に関連付け。
何に対して関連付けしたらいいの?という疑問。
どうやらIntaractivObjectという抽象クラスがあって、サブクラスにDisplayObjectContainer, SimpleButton, TextFieldを持っており、そのクラスのcontextMenuプロパティを使って設定している模様。

ってさぁ、StageってDisplayObjectContainerを継承してて、contextMenuプロパティもあるのになんでぇ〜?って感じなんですけど。
で、スプライトには設定できるようなので、ステージサイズの透明な図形を描画したスプライトをメインに動的配置してみたら、静的に配置したボタンが反応しなくなったという罠orz

で、検索しまくって出てきたのが、thisターゲットだった。
thisってなんだ?
まぁ、当たり前ですけど、trace(this)ってかいたら
  Object MainTimeline
うんうん、だよねー。
よくわからんけど、Objectには設定できるらしい(謎)。
posted by K at 15:39| Comment(0) | スクリプト | このブログの読者になる | 更新情報をチェックする

ムービークリップの配置と削除

覚書です。


addChildで配置したMCから、自身を削除する命令を出したい場合の処理

難儀なことで removeChild(this); とか書くと、エラーが出る。
削除したいターゲットが、発信元の子オブジェクトじゃないと受け付けてくれないんだとさ。。。
つまりステージに配置した場合は、removeChild()はメインタイムラインに書かなくちゃいけない。

で、以下の二つを試してみる。
(その1)配置したbtnボタンで削除
(その2)特定のフレームまで再生されたら削除


(1)配置用のムービークリップ:childを作成。
アクションスクリプト用に書き出しにチェックを入れる。
addChild.bmp

(2)ステージにchildを配置
メインタイムラインに以下を記述
//インスタンス作成
var child_mc:child = new child();

//ルートに表示オブジェクトを追加
addChild(child_mc);

//child_mcのbtn処理(その1用)
child_mc.btn.addEventListener('click',onClick);
function onClick(event:MouseEvent):void{
removeChild(child_mc);
removeEventListener('click', onClick);
}

//child_mcを消す関数(その2用)
function reChild():void{
removeChild(child_mc);
}



その1の処理は、これで終わり。
ボタンを押すとchild_mcが消える。

その2は、childムービークリップ内の、特定のフレームでreChild関数を呼び出す処理を加える。
MovieClip(parent).reChild();
this.stop();


最後のthis.stop();を書かないでいると、消えてから暫くして次のようなエラーが出る。
TypeError: Error #1009: null のオブジェクト参照のプロパティまたはメソッドにアクセスすることはできません。
at child/frame19()

1回目は実行されたけど、ループして2回目はchild_mcが存在しないのでエラーが出たということだろうか。
だとすれば、消えたけど生き続けていて、スクリプトは実行されてるんだ。
childの中に、EnterFrameなどの処理を書いている場合、removeChild()と同時にEnterFrameの処理をしているイベントリスナーも削除しなければ、延々と処理しつづけることになるので注意!

posted by K at 13:58| Comment(0) | スクリプト | このブログの読者になる | 更新情報をチェックする

2010年07月15日

addEventListener

addEventListenerの覚書

(1)gotoAndStop()で移動する場合は注意!
例えば、下のような配置の場合
addEventListener1.bmp
this.gotoAndStop(15);

btn.addEventListener('click', onBtn);
function onBtn(e:MouseEvent):void{
trace(currentFrame);
}

ジャンプ先でもイベントリスナーは有効になっており、15と出力される。

しかし、下のような配置の場合
addEventListener2.bmp
ジャンプ先では、イベントリスナーは無効になっており、何も出力されない。
この場合は、ジャンプ先で、再度イベントリスナーを追加しなければならない。

//フレーム15のスクリプト
btn.addEventListener('click',onBtn);

リスナー関数は1フレーム目に定義してあるので、呼び出すだけで良い。

同じリスナー関数を重複して追加しても、2度実行されることはない。


(2)リスナー関数に引数を渡す方法
関数内で、イベントを受け取る関数を作成する。
関数内で作成された関数は、ローカル変数をそのまま使える。

//リスナー関数
function myFunc(param){
return funcion (event:MouseEvent):void{
trace(param);
trace(event);
}
}

//引数となる変数の作成
var param:String = "引数";

//イベントリスナーの登録
stage.addEventListener('click', myFunc(param));

出力結果
引数
[MouseEvent type="click" bubbles=true cancelable=false eventPhase=2
localX=82 localY=87 stageX=82 stageY=87 relatedObject=null
ctrlKey=false altKey=false shiftKey=false buttonDown=false delta=0]

変数paramを使わなくてもそのまま値を引数にしてもOK。
posted by K at 10:26| Comment(0) | スクリプト | このブログの読者になる | 更新情報をチェックする