AS3ではMovieClipの階層構造の縛りから開放される!
AS2ではMovieClip(TextField)のインスタンス化は親(AS2以前は_parent、AS3ではparent)がいて始めてできることでした(_rootを除く)。そして後から親を変える(つまり別のMovieClip階層に移動する)ことはできませんでした。
AS3(ActionScript 3.0)では親がいなくても生まれます(インスタンス化)。そして後から親を決められます。さらに親を変えることもできます。
別の言い方をすると、AS2ではインスタンス化されると同時に画面に表示される対象になりますが、
AS3ではインスタンス化後、好きな階層に好きなタイミングでMovieClip(TextField)の出し入れ(画面に表示する対象にするか、しないか)ができます。
出し入れはaddChild()とremoveChild()でおこないます。
これは本当に衝撃的でMovieClipの階層構造の縛りから開放される感じがします。
これができるということは、
例えば、(内部に多数のコンポーネントを保持するなど)インスタンス化の負荷が高いMovieClipを複数回画面に登場されるような場合に、そのMovieClipをメモリ上にプールしておくようなテクニックが使えそうです。今までも一度インスタンス化したらあとは_visibleをコントロールすることで2回目以降のインスタンス化を行わないなどするテクニックはありましたが、MovieClip階層の変更はできませんし、非表示であってもおそらく、Flash Playerの画面描画処理の負荷になっていたでしょう。
AS3ではaddChild()とremoveChild()によって同様のことができるようになり、さらに後からMovieClip階層の変更はできるし、単なる非表示ではなく完全に描画対象でなくすことができるので、恐らく画面描画処理の負荷も下がるでないかと思います。
これを応用すれば、何度も使うクラスのインスタンスを再利用する、デザインパターンでいうとFlyweightみたいなことができそうです。
特に、ListやDataGridのようなコンポーネントで使えるんじゃないかと思います。もしかしたらFlex 2.0のコンポーネントはすでにそのようなテクニックを使ってるかも知れないですね。
コンポーネントのソースを見る方法はあるのかな?
最後に
TextFieldの階層を移動させたり、描画対象からはずしたりするサンプルです。
[code]
package {
import flash.util.trace;
import flash.display.StageScaleMode;
import flash.display.StageAlign;
import flash.display.Sprite;
import flash.display.DisplayObject;
import flash.display.MovieClip;
import flash.display.SimpleButton;
import flash.display.TextField;
import flash.display.TextFieldType;
import flash.display.TextFieldAutoSize;
import flash.text.TextFormat;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.events.MouseEventType;
public class ASProjectTest extends MovieClip {
// 親がえするTextField(traceFTの出力先でもある)
private var tf:TextField;
// コンストラクタ
public function ASProjectTest() {
initApp();
}
private function initApp():Void {
// ステージを拡大縮小させずに、左上寄せにする
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
// 親がえするTextField(traceFTの出力先でもある)
tf = new TextField();
tf.x = 10;
tf.y = 10;
tf.width = 200;
tf.height = 200;
tf.multiline = true;
tf.background = true;
tf.type = "input";
this.addChild(tf);
traceFT("テキストフィールド", "第2引数");
// 青い四角
var mc1:MovieClip = new MovieClip();
mc1.x = 10;
mc1.y = 250;
mc1.graphics.beginFill(0x0000CC, .5);
mc1.graphics.lineStyle(3, 0x000066);
mc1.graphics.drawRect(0, 0, 220, 220);
mc1.graphics.endFill();
mc1.addEventListener(MouseEventType.CLICK, onClick_addChild);
mc1.useHandCursor = true
this.addChild(mc1);
// 緑の角丸四角
var mc2:MovieClip = new MovieClip();
mc2.x = 270;
mc2.y = 250;
mc2.graphics.beginFill(0x00CC00, .5);
mc2.graphics.lineStyle(3, 0x006600);
mc2.graphics.drawRoundRect(0, 0, 220, 220, 10);
mc2.graphics.endFill();
mc2.addEventListener(MouseEventType.CLICK, onClick_addChild);
this.addChild(mc2);
// 赤丸
var mc3:MovieClip = new MovieClip();
mc3.x = 530;
mc3.y = 250;
mc3.graphics.beginFill(0xCC0000, .5);
mc3.graphics.lineStyle(3, 0x660000);
mc3.graphics.drawCircle(110, 110, 110);
mc3.graphics.endFill();
mc3.addEventListener(MouseEventType.CLICK, onClick_addChild);
this.addChild(mc3);
// ラベル表示用
var label:TextField = new TextField();
label.x = 300;
label.y = 10;
label.autoSize = TextFieldAutoSize.CENTER ;
label.selectable = false;
label.background = false;
label.border = false;
label.text = "removeChild()";
this.addChild(label);
// シンプルボタンのアップとダウン状態のスキン
var upSprite:Sprite = new Sprite();
upSprite.graphics.lineStyle(2, 0x202020);
upSprite.graphics.beginFill(0xBBBBBB);
upSprite.graphics.drawRoundRect(0, 0, 100, 50, 5);
// シンプルボタンのオーバー状態のスキン
var overSprite:Sprite = new Sprite();
overSprite.graphics.lineStyle(2, 0x202020);
overSprite.graphics.beginFill(0xCCCCCC);
overSprite.graphics.drawRoundRect(0, 0, 100, 50, 5);
// シンプルボタン(UIコンポーネントではない)
var myButton:SimpleButton = new SimpleButton();
myButton.upState = upSprite;
myButton.overState = overSprite;
myButton.downState = upSprite;
myButton.useHandCursor = true;
myButton.hitTestState = upSprite;
myButton.x = 300;
myButton.y = 30;
myButton.addEventListener(MouseEventType.CLICK, onClick_removeChild);
this.addChild(myButton);
}
public function onClick_addChild(event:MouseEvent):Void {
traceFT("onClick_addChild", event);
var target:MovieClip = MovieClip(event.currentTarget);
// TextFieldをクリックされたMovieClipの子に追加する。
// もし、すでにTextFieldが他の子であった場合は、親が変わることになる
target.addChild(tf);
}
public function onClick_removeChild(event:MouseEvent):Void {
traceFT("onClick_removeChild", event);
if (tf.parent) {
// TextFieldを親との縁をきらせる。
// 画面から消えるけどインスタンスとしてはメモリ上に残る。
tf.parent.removeChild(tf);
}
}
// TextFieldに出力する
// 「... args」という書き方で複数の引数を受け取れる
public function traceFT(... args):Void {
var log:String = args.join(" ");
tf.text += log + "\n";
trace(log);
}
}
}
[/code]
トラックバック(0)
このブログ記事を参照しているブログ一覧: AS3ではMovieClipの階層構造の縛りから開放される!
このブログ記事に対するトラックバックURL: http://uenon.jp/mt/mt-tb.cgi/73

コメントする