Flexの最近のブログ記事

FlashBuilder4から簡単にアイテムレンダラーの設定を行う事が可能となりました。
今回はその方法の紹介として、データグリッドにカスタムレンダラー部品を埋め込んだサンプルを作成してみます。

最初に、メインアプリケーションを作成します。 サンプルでは、<s:Panel>内 に<mx:DataGrid>を配置しました。
メインアプリケーションのcreationCompleteハンドラでデータグリッドの表示データを設定します。 ji6-1.png


	
		
	

	
	
	
		
	

	
		
			
				
				
				
				
				
				
			
		
	

[実行結果]
ji6-2.png

上記データグリッドのチェック列にチェックボタンを表示し、チェックボタンが選択された場合、チェックボタンの横に「選択済」と文字列が表示されるようにアイテムレンダラーを設定しようと思います。

mxmlのデザインビューでデータグリッドを選択し、プロパティにて「列の構成」ボタンをクリックします。
ji6-3.png

ここでは、ヘッダーテキストの値や幅などのプロパティの設定をはじめ、詳細ビューでは詳細な設定をおこなう事が可能です。データバインディングの欄にアイテムレンダラーの設定欄がありますので、横の紫のボタンをクリックし「アイテムレンダラーを作成」をクリックします。
ji6-4.png

パッケージとコンポーネント名を入力し終了ボタンをクリックします。
ji6-5.png

終了ボタンをクリックすると「列の構成」設定画面に戻ってくるので、先ほど作成したコンポーネントがアイテムレンダラー欄に設定されている事を確認しOKボタンをクリックします。
ji6-6.png

設定が完了するとパッケージエクスプローラー上に、先ほどアイテムレンダラーで設定したコンポーネントが作成されている事が確認できると思います。更に先ほどの設定で自動的に<mx:DataGridColumn>にitemRendererが設定されます。

次にアイテムレンダラーの部品を編集します。
<s:CheckBox>を配置しクリックハンドラ内でチェックボックスが選択された場合、チェックボックスのlabelプロパティの値に”選択済”を設定します。
ji6-7.png
デザインビューでサクサク設定を行えるので、多彩な表現を簡単に設定できるのは非常に嬉しいです。
以下はコードになります。



	
		
	

	
	
		


以上で設定は完了です。実際に実行したイメージは以下の様になります。ji6-8.png

GUIで簡単にアイテムレンダラーの設定を行う事が可能となったのでFlexに慣れていない方もサクサク色々な事ができるようになったのではないでしょうか?

つい先日、FlashBuilder4が発売となりました。

今回は、FlashBuilder4にて簡単なFlexアプリケーションを作成し、新機能などを紹介したいと思います。

Flash Builder4は公式サイトより体験版が入手可能です。

http://www.adobe.com/jp/products/flashbuilder/?view=topnew

 

まずはじめに、Flexプロジェクトを作成します。


1.パッケージエクスプローラーで右クリックし「Flexプロジェクト」を選択しプロジェクトを作成します。

2. アプリケーションの種類は「Web(Adobe Flash Playerで実行)」を選択し終了ボタンをクリックします。

ji5-1.pngのサムネール画像のサムネール画像

作成されたプロジェクト内のmxmlを見てみると、<s:Application>のようにsparkコンポーネントベースでApplicationが作成されます。
従来(Flex3まで)はFlex標準コンポーネントは、ネームスペースmxで始まるHaloコンポーネントで構成されておりましたが、FlashBuilder4からネームスペースsで始まるSparkコンポーネントが追加されました。
Flex標準コンポーネントの<TextInput>や<Panel>などのおなじみの部品もHaloコンポーネントとSparkコンポーネントでそれぞれ存在します。
プロジェクト作成時に自動的に作成されるmxmlのソースを見てみると<fx:Declarations>など、従来になかった表記がされています。
これらmxml2009に関する詳細は、「Flex4マスターシリーズ」で詳しく説明されておりますのでそちらもご参照ください。

http://www.adobe.com/jp/devnet/flex/articles/flex4_tutorials.html

 

次にデザインビューにて、コンポーネントを配置し画面を作成します。
サンプルでは以下のログインフォームの様な画面を作成しました。

ji5-2.png

<?xml version="1.0" encoding="utf-8"?>

	
		
	
	
		
			
				
					
					
				
					
					
						
					
					
        		
			
		
	

ここから、デザインビューでデザインの詳細設定を行っていこうと思います。
まず、ログインフォーム内(s:Panel)に配置されたVGroupのパディングを設定します。
FlashBuilder4からは、デザインビューのプロパティからパディングの設定も行う事が可能となりました。
以下の通り、全て10で設定します。

ji5-3.png

次にログインボタンをクリックするとアラートを表示する機能を実装します。
<s:Button>にclick=""と入力するとコードアシストの候補に「Clickハンドラーを作成」と表示されます。

ji5-4.png

「Clickハンドラーを作成」を選択すると、mxml内に「部品id+イベントハンドラ」と命名されたイベントハンドラが自動生成されます。
これもFlashBuilder4から追加された機能となりますがなかなか便利です。

ji5-5.png

作成されたイベントハンドラにアラートを実装します。

サンプルでは以下の通り実装しました。

;


	
		
	


	
		
	
	
		
			
				
					
				
				
					
				
			
			
		
	

 

次に、今回から追加された、「Flexテーマの変更」を行ってみようかと思います。
Flexプロジェクトを右クリックし、「Flexテーマ」を選択します。

ji5-6.png

FlashBuilder4からは「Flexテーマ」の変更によって簡単に外観を変更する事が可能です。
デフォルトは「Adobeテーマ - Spark」が選択されているので、他のテーマを選択しOKボタンをクリックします。

[デフォルト:Spark]

ji5-7.png

[Arcade]

ji5-8.png

以上でサンプルは完成です。

今回は、ボタンをクリックするとアラートが表示されるだけという非常に簡単なサンプルでしたが、それだけのアプリケーションを作成するに当たって、色々な変更点を紹介する事が出来ました。
もちろんこれだけではなく非常に多くの変更点がありますので
早めに、FlashBuilder4をいじり倒してみる事をお勧めします。

データグリッドのアイテムレンダラーを使用していて、コンテナを使用しているカスタムコンポーネントでも、TABキーを押下して順々に各コントロールにフォーカスが移動できれば、慣れたユーザーなら操作が便利になるかと思います。

例えば、VBoxコンテナに TextInput を2つ並べたカスタムコンポーネントのアイテムレンダラーの場合、TABキーを押下したときに下記のような感じでフォーカスが移動するイメージです。

tab-itemrenderer.jpg 画像1.TABキー押下時のフォーカス移動のイメージ

もっとスマートな方法もあるかと思いますが、とりあえずアイテムレンダラーに使うカスタムコンポーネントに以下のカスタマイズを加えることで自分がやりたいことを実現しました。

※今回の例では、フォーカス移動に焦点をあてているので、データを表示するアイテムレンダラーのカスタムコンポーネントとしては不完全ですのでご注意ください。

MXML

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"	xmlns:local="*">
	<mx:Script>
		<![CDATA[
			[Bindable]
			private var dgData:Array = [
			{no:1, name:'氏名1', age:21, address:'住所1'},
			{no:2, name:'氏名2', age:22, address:'住所2'},
			{no:3, name:'氏名3', age:23, address:'住所3'},
			{no:4, name:'氏名4', age:24, address:'住所4'},
			{no:5, name:'氏名5', age:25, address:'住所5'}
			];
		]]>
	</mx:Script>
	<mx:DataGrid dataProvider="{dgData}" editable="true">
		<mx:columns>
			<mx:DataGridColumn headerText="列1" dataField="no" editable="false"/>
			<mx:DataGridColumn headerText="列2" rendererIsEditor="true" editorDataField="">
				<mx:itemRenderer>
					<mx:Component>
						<local:TabMove verticalScrollPolicy="off" horizontalScrollPolicy="off"/>
					</mx:Component>
				</mx:itemRenderer>
			</mx:DataGridColumn>
			<mx:DataGridColumn headerText="列3" rendererIsEditor="true">
				<mx:itemRenderer>
					<mx:Component>
						<local:TabMove verticalScrollPolicy="off" horizontalScrollPolicy="off"/>
					</mx:Component>
				</mx:itemRenderer>
			</mx:DataGridColumn>
		</mx:columns>
	</mx:DataGrid>
</mx:Application>

このMXMLは、下記のカスタムコンポーネントを実装しているだけです。注意点は↓の記事と同じになりますので参照してください。

[Flex]データグリッド内の単純なアイテムレンダラーでTABキーを押下してフォーカスを移動する

 

カスタムコンポーネント

package
{
	import flash.accessibility.AccessibilityProperties;
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	import flash.display.LoaderInfo;
	import flash.display.Sprite;
	import flash.display.Stage;
	import flash.events.Event;
	import flash.events.FocusEvent;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.geom.Transform;
	import flash.ui.Keyboard;
	
	import mx.containers.VBox;
	import mx.controls.TextInput;
	import mx.controls.listClasses.BaseListData;
	import mx.controls.listClasses.IDropInListItemRenderer;
	import mx.controls.listClasses.IListItemRenderer;
	import mx.managers.IFocusManager;
	import mx.managers.IFocusManagerComponent;
	import mx.managers.ISystemManager;

	public class TabMove extends VBox
	implements IListItemRenderer, IDropInListItemRenderer, IFocusManagerComponent
	{
		public function TabMove()
		{
			super();
		}
		
		/** テキストインプット1 */
		private var text1:TextInput = null;
		/** テキストインプット2 */
		private var text2:TextInput = null;

		public var text:String = "";

		//----------------------------------
		//  listData
		//----------------------------------
		
		private var _listData:BaseListData;

		[Bindable("dataChange")]
		[Inspectable(environment="none")]
		public function get listData():BaseListData
		{
			return this._listData;
		}
		
		public function set listData(value:BaseListData):void
		{
			this._listData = value;
		}
		
		override protected function createChildren():void
		{
			super.createChildren();
			
			this.text1 = new TextInput();
			this.text1.addEventListener(FocusEvent.KEY_FOCUS_CHANGE, keyFocusChangeHandler);
			addChild(this.text1);
			
			this.text2 = new TextInput();
			addChild(this.text2);
		}
		
		private function keyFocusChangeHandler(event:FocusEvent):void
		{
			if (event.keyCode == Keyboard.TAB &&
				!event.isDefaultPrevented())
			{
				event.preventDefault();
				
				if (event.currentTarget == this.text1)
				{
					var fm:IFocusManager = this.focusManager;
					fm.setFocus(IFocusManagerComponent(this.text2));
				}
			}
		}

		override public function setFocus():void
		{
			var fm:IFocusManager = this.focusManager;
			if (IFocusManagerComponent(this.text1) != fm.getFocus() &&
				IFocusManagerComponent(this.text2) != fm.getFocus())
				fm.setFocus(IFocusManagerComponent(this.text1));
		}
	}
}

上記の例ではコンテナ内のコンポーネントは2つですが、ソースを工夫することで3つでも4つでも問題は無いと思います。

TABキー押下時にカスタムコンポーネントでフォーカス移動を実現させるために、カスタムコンテナに IFocusManagerComponent インタフェースを実装します。
これによりDataGrid コンポーネントで、アイテムレンダラー間のフォーカスの移動をやってくれます。

次に、コンテナ内の子コンポーネント作成時に、TABキー押下時に次のフォーカスをあてるコンポーネントが、同じカスタムコンポーネント内の場合は、KEY_FOCUS_CHANGE イベントを追加しておきます。

今回の例では、上段の TextInput にイベントを追加しています。

this.text1.addEventListener(FocusEvent.KEY_FOCUS_CHANGE, keyFocusChangeHandler);


そして、そのイベントリスナーメソッドで、TABキーを押されたときはイベントをキャンセルし、次にフォーカスを移動させたいコンポーネントに対してフォーカス移動を行います。

				event.preventDefault();
				
				if (event.currentTarget == this.text1)
				{
					var fm:IFocusManager = this.focusManager;
					fm.setFocus(IFocusManagerComponent(this.text2));
				}

こうしないと、TABキーを押下したときに、カスタムコンポーネント内ではなく、DataGrid のカスタムコンポーネント間でフォーカスが移動してしまいます。

tab-itemrenderer2.jpg

画像1.カスタムコンポーネント間でフォーカスが移動してしまう例

次に、SetFocus メソッドをオーバーライドします。

		override public function setFocus():void
		{
			var fm:IFocusManager = this.focusManager;
			if (IFocusManagerComponent(this.text1) != fm.getFocus() &&
				IFocusManagerComponent(this.text2) != fm.getFocus())
				fm.setFocus(IFocusManagerComponent(this.text1));
		}

DataGrid コンポーネントは、TABキーなどでフォーカスを移動するときはアイテムエディターコンポーネント自体にフォーカスを移動します。
今回の例では VBox コンテナにフォーカスが移動してしまうわけです。
使う側からすれば、VBox コンテナにフォーカスが移動しても困るので、ここの処理で、フォーカスがコンテナの子コンポーネント以外のときは、一番最初にフォーカスを当てたいコンポーネントにフォーカスを移動させています。

ここまでで、大体やりたいことが出来るようになりました。

ただし、アイテムエディターでは、Enterキーを押したときは横方向ではなく下方向にフォーカスが移動していきます。
今回の方法では、Enterキーについてはカスタムコンポーネント間でフォーカスが移動してしまいます。
業務での優先順位が低いこともあり、そこはただいま調査中です。

データグリッドでアイテムエディターを使用すると、TABキーを押下したときに次のコントロールに遷移してくれます。

しかし、アイテムレンダラーを使用すると、TABキーを押下しても次のコントロールに遷移してくれません。

どうすれば実現できるかを調べたところ、単純なアイテムレンダラーであれば、アイテムエディターのようにTABキーを押下したときに次のコントロールに遷移させる方法は、簡単なプロパティの設定だけで実現できることがわかりました。

以下、その方法を簡単にご紹介します。

①データグリッドコントロールの editable プロパティを trueにします。
<mx:DataGrid editable="true">

※このプロパティを true に設定すると、データグリッド内の各列に アイテムエディターが作成されるので、不要な列は DataGridColumnの editable プロパティを false に設定します。

②アイテムエディターのインスタンスが必須ですので、アイテムレンダラーとアイテムエディターが同じ場合は、DataGridColumnの rendererIsEditor プロパティを false に設定します。
    <mx:DataGridColumn headerText="列2" dataField="name"
        rendererIsEditor="true" itemRenderer="mx.controls.TextInput"/>

簡単なサンプルを下記に示します。

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" xmlns:local="*">
	<mx:Script>
		<![CDATA[
			[Bindable]
			private var dgData:Array = [
			{no:1, name:'氏名1', age:21, address:'住所1'},
			{no:2, name:'氏名2', age:22, address:'住所2'},
			{no:3, name:'氏名3', age:23, address:'住所3'},
			{no:4, name:'氏名4', age:24, address:'住所4'},
			{no:5, name:'氏名5', age:25, address:'住所5'}
			];
		]]>
	</mx:Script>
	
	<mx:DataGrid dataProvider="{dgData}" editable="true">
		<mx:columns>
			<mx:DataGridColumn headerText="列1" dataField="no" editable="false"/>
			<mx:DataGridColumn headerText="列2" dataField="name"
				rendererIsEditor="true" itemRenderer="mx.controls.TextInput"/>
			<mx:DataGridColumn headerText="列3" dataField="address"
				rendererIsEditor="true" itemRenderer="mx.controls.TextInput"/>
		</mx:columns>
	</mx:DataGrid>
</mx:Application>

単純な アイテムレンダラー(コンテナが無いコンポーネント)であれば、これだけです。一見したら何もしていないようにも見えます(^^;)

この方法は、FXUGのフォーラム(⇒ここ)で見つけました。

しかし、コンテナがあるアイテムレンダラー(1つのアイテムレンダラー内に複数のコンポーネントがある)のように、まずアイテムレンダラー内だけでフォーカス遷移し、最後のコンポーネントでTABキーを押下されたときに、次のアイテムレンダラーに移るといったような複雑なことを実現するには、少々アイテムレンダラーに使用するコンポーネントをカスタマイズする必要があります。

それについては、次回ご紹介します。
 

ブラウザのタイトル設定方法を紹介します。
設定方法は難しくないのですが、いくつか注意すべき点が存在します。


mxmlの<Application>のpageTitleプロパティを使用すると、
ブラウザのタイトル部分に表示するタイトルを設定する事が可能です。

■メインアプリケーション(mxml)
 

<?xml version="1.0" encoding="utf-8"?>

	



実際にswfコンテンツがのっているhtmlは、ビルド時に
index.template.htmlを元に生成されますが、この時<Application>のpageTitleの値を参照し
htmlの<titlle>に設定を行います。


■index.template.html

<title>${title}</title>

  ↓ビルドでhtmlが生成される

■XXXXX.html

<title>mxmlで設定したタイトル名</title>


わざわざアプリケーション側で設定しなくても、index.template.htmlのtitleを直接変更すれば
シンプルな設定となりますが、実はこの方法ではtitleに日本語を設定してしまうと
タイトルが文字化けしてしまいます。



■index.template.html

<title>テストページ</title>

  ↓
■XXXXX.html

<title>繝�繧ケ繝医�壹�シ繧ク</title>


その為、タイトルの設定は<Application>のpageTitleプロパティで設定する必要がありますが、更に注意点が存在します。

通常、自動生成されるhtmlのエンコードはUTF-8ですが、
エンコーディングをUTF-8以外に変更した場合、title部分が文字化けしてしまいます。

文字化けしてしまった部分を直接修正する方法もアリですが、
ビルドの度に生成されるファイルなので、都度修正が必要になってしまいます。
(デグレード等を引き起こす可能性があるため危険です)

そこでオススメなのが、JavaScriptでタイトルを設定する方法です。
この方法ならば文字化けも解消でき、かつ動的にタイトルの設定を行う事が可能となります。
以下がサンプルです。
■アプリケーション側

// ウインドウの切り替え
ExternalInterface.call('setTitle',viewName);


■html側(JavaScript)

<script language="JavaScript" type="text/javascript">

	// windowのタイトルを設定
	function setTitle(ttl)
	{
		window.document.title = ttl;
	}
</script>

html側(index.template.htmlに実装)にタイトル設定用のJavaScriptを用意し タイトル設定を行うタイミング時、画面側でExternalInterfaceを使用しJavaScriptの呼び出しを行います。 この方法を使用した場合、動的にタイトルの値を変更する事も可能となるのでオススメです。

<<前のページ 12345

このブログについて

このブログは吉祥寺にあるブレインチャイルド株式会社の社員で投稿しています。
業務ではまってしまったことや発見したこと。
自分達で新たに学習してみようと思って勉強し始めたことなどを綴っています。
こんな社員が働いているブレインチャイルドに興味がわいててきたなら、是非お問い合わせください。
会社案内
求人案内
先輩のコメント