【Flex3】「Flex3の、こんなときどうするの??」
こんにちは、最近モールス信号に興味深々の橋本です。
さて、今回は前回の「AS3のこんなときどうするの?」の続編で、
「Flex3のこんなときどうする?」をテーマに、また思いついたところを適当に書いていきたいと思います。
今アサイン されてるプロジェクトを進める中で発見したものばかりなので、結構偏りがあるかもしれませんが、そこはご了承くださいませ。。。
では、どぞー。
1. スクリプトの中で値をバインドしたい
Q. mxmlの中で値をバインドするときには、バインドしたい変数をmxmlの中で{}で囲み、対象の変数に、[Bindable]タグをつければオッケーなんだけど、スクリプトの中で、値をバインドさせたいときはどうするの??
A. BindingUtilsクラスを使いましょう。
BindingUtils.bindProperty()を使うことで、プロパティ同士をバインドさせることができます。
var textInput:TextInput = new TextInput();
addChild(textInput);
var label:Label = new Label();
addChild(label);
BindingUtils.bindProperty(label, "text", textInput, "text");
bindSetterメソッドを使うことで、対象の変数が変化したときに、特定のメソッドを呼び出すこともできますよ。
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" minWidth="1024" minHeight="768"
creationComplete="application1_creationCompleteHandler(event)"
>
<mx:TextInput id="textInput"/>
<mx:Label id="hoge"/>
<mx:Script>
<![CDATA[
import mx.binding.utils.BindingUtils;
import mx.controls.Label;
import mx.controls.TextInput;
import mx.events.FlexEvent;
protected function application1_creationCompleteHandler(event:FlexEvent):void
{
BindingUtils.bindSetter(toUpperCase, this.textInput, "text");
}
private function toUpperCase(str:String):void
{
this.hoge.text = str.toUpperCase();
}
]]>
</mx:Script>
</mx:Application>
2. 自分で作ったクラスのプロパティをバインドの対象にしたい
Q. 自分で作成したクラス内のプロパティをバインドの対象にしたい。でも、呼び出し元で[Bindable]タグをつけるわけにもいかないし、BindingUtils使おうと思っても、対象外って怒られるし、どうするの??
A. 自分で作成したクラス内の変数のセッター内で、イベントをdispatch。Bindableタグの中で、そのイベントを指定するとバインドの対象にできますよ。
こんな感じです。
var hoge:String;
//セッターの中で、設定したイベントをdispatch。Bindableタグで、イベントを指定
[Bindable(event="hogeChange")]
public function set hoge(value:String):void
{
dispatchEvent(new Event("hogeChange"));
hoge = value;
}
3. 独自イベントをmxmlの選択項目にいれたい
Q. 自分でカスタムしたコンポーネントを呼び出すときに、独自イベントをmxmlで指定したいんだけど、どうするの??
A. コンポーネント内のMetadataタグの中にイベント名を記載しておきましょう。そうすることで、後からmxml上で使うことができます。
<mx:Metadata>
[Event(name="hoge",type="flash.events.Event")]
</mx:Metadata>
4. DataGridの背景色を変更したい
Q. DataGridの背景色をセル毎に変えたいんだけど、どうするの??
A. DataGridColumnのitemRendererのbackgroundプロパティをtrueにして、backgroundColorを設定することで変更できますよー。
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" minWidth="1024" minHeight="768"
xmlns:components="components.*"
creationComplete="application1_creationCompleteHandler(event)"
>
<mx:DataGrid dataProvider="{dataList}"
width="100%"
height="100%"
>
<mx:columns>
<mx:DataGridColumn headerText="hoge" dataField="data" itemRenderer="components.Hoge"/>
</mx:columns>
</mx:DataGrid>
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.events.FlexEvent;
[Bindable]
private var dataList:ArrayCollection;
protected function application1_creationCompleteHandler(event:FlexEvent):void
{
var arr:ArrayCollection = new ArrayCollection();
for (var i:int = 0; i < 100; i++)
{
var obj:Object =
{
data: i
}
;
arr.addItem(obj);
}
dataList = arr;
}
]]>
</mx:Script>
</mx:Application>
itemRenderer用のクラス
package components
{
import mx.controls.dataGridClasses.DataGridItemRenderer;
public class Hoge extends DataGridItemRenderer
{
public function Hoge()
{
super();
this.background = true;
// ランダムの色を入れる
this.backgroundColor = Math.random() * 0xFFFFFF;
}
}
}
5. DataGridに文字列以外のものを表示したい
Q. DataGridに、ボタンとか画像とかチェックボックスとか、その他諸々を表示したいんだけど、どうするの??
A. DataGridColumnのitemRendererに、表示したいコンポーネントのクラスを指定することで変更することができますよー。
mxmlで指定するときには、一つ前のサンプルの中でやっているような感じで、クラス名を指定してやればオッケーです。
スクリプトで指定するときには、ClassFactoryクラスのインスタンスを指定してやればオッケーです。
var column:DataGridColumn = new DataGridColumn();
column.itemRenderer = new ClassFactory(Hoge);
6. ツリーに文字列以外のものを表示したい
Q. ツリーにボタンとか画像とかチェックボックスとか、その他諸々を表示したいんだけど、どうするの??
A. DataGridのときと同様に、itemRendererを指定することで可能です。
ただ、チェックボックスを表示するときは要注意。DataGridやTreeなどの、ListベースのコンポーネントのitemRendererは内部で使いまわされるので、チェックした状態を保持しておく機構が必要です。
以下の例では、TreeのdataProviderに指定しているXMLに、selectedというAttributeを持たせて、それを変更することによって、チェック状態を保持しています。
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" minWidth="1024" minHeight="768"
xmlns:components="components.*"
>
<mx:Tree itemRenderer="components.Hoge" dataProvider="{xml}" width="100" labelField="@value"/>
<mx:Script>
<![CDATA[
[Bindable]
private var xml:XMLList = XML(
<root>
<node selected="false" value="1"/>
<node selected="false" value="2"/>
<node selected="false" value="3"/>
<node selected="false" value="4"/>
<node selected="false" value="5"/>
<node selected="false" value="6"/>
<node selected="false" value="7"/>
<node selected="false" value="8"/>
<node selected="false" value="9"/>
<node selected="false" value="10"/>
</root>
).node;
]]>
</mx:Script>
</mx:Application>
チェッ クボックスを表示するためのカスタムitemRendererクラス
package components
{
import mx.binding.utils.BindingUtils;
import mx.controls.CheckBox;
import mx.controls.treeClasses.TreeItemRenderer;
import mx.controls.treeClasses.TreeListData;
public class Hoge extends TreeItemRenderer
{
[Bindable]
public var checkBox:CheckBox;
public function Hoge()
{
super();
}
override public function set data(value:Object):void {
super.data = value;
}
override protected function createChildren():void{
super.createChildren();
checkBox = new CheckBox();
checkBox.setStyle("verticalAlign","middle");
BindingUtils.bindSetter(setSelected, checkBox, 'selected');
this.addChild(checkBox);
}
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void {
var treeListData:TreeListData = TreeListData(super.listData);
super.updateDisplayList(unscaledWidth,unscaledHeight);
if(super.data)
{
if (data.@selected.toString() == 'true')
{
checkBox.selected = true;
}
else
{
checkBox.selected = false;
}
checkBox.x = super.label.x;
checkBox.y = ( unscaledHeight - checkBox.height ) /2;
label.x = checkBox.x + checkBox.width + 20;
}
}
private function setSelected(selected:Boolean):void
{
if (data)
{
data.@selected = selected.toString();
}
}
}
}
7. drag and drop時の画像を変更したい
Q. drag and dropを独自に実装したときに、ドラッグする対象の画像を変更したいんだけど、どうするの??
A. DragManagerクラスのdoDragメソッドの第四引数に画像を指定してやればオッケーです。
DragManager.doDrag(dragInitiator, dragSource, event, img);
8. カーソルを変更したい
Q. 処理待ち中のカーソルを 変更したりしたいんだけど、どうするの??
A. cursorManager変数の各種メソッドを使えば可能ですよー。
cursorManager.setBusyCursor()で、デフォルトの時計のアイコンを表示することができます。
cursorManager.removeBusyCursor()で、普通のアイコンに戻せます。
CursorManager.setCursor()を使うことで、独自のアイコンを指定することもできますよー。
9. ラッパーのhtmlのtitleをswfの中で設定したい
Q. htmlのタイトルを変更したいんだけど、どうするの??
A. ExternalInterfaceクラスを使いましょう。そうすることで、swfから、javascriptを実行することができます。
ExternalInterface.call("function(){if(location.href.indexOf('#',0) != -1){document.title = 'hogehoge'}}");
ラッパーhtmlの中でタイトルを最初から指定しておけばいいんじゃネーノ?って思うかもしれませんが、IEだけちゃんと動かないんですよ。なぜか'#'って表示されちゃうんですよね。
10. swfの置いてあるURLを取得したい
Q. swfの実行元のURLを取得して、swfの内部で使いたいんだけど、どうするの??
A. Application.application.urlで、実行されているswfのURLをフルで取得できるので、そこから正規表現で取得しましょう。
private function getHost():String
{
var fullUrl:String = Application.application.url;
var reg:RegExp = new RegExp("http://[^/]*/");
if (reg.test(fullUrl)) {
return reg.exec(fullUrl).toString();
}
}
以上でーす。
結構偏った内容なんですが、お役にたてることが一つでもあれば幸いです。
ではではー。