ブラウザでダウンロード メニューのアイコンについて2008/11/22 時点の 3.1.0 build 2710 において、XML でメニュー処理すると アイコンが使用できません。 iconFunction プロパティを使用すると、表示はされますが( 機能は正常 ) アイテム毎のコントロールができません。明らかにバグです。 それでも、アイコンを使用しなければ XML を使用できるので、それはそれで 良いのですが、プロパティの参照に XML 仕様の "@" を使用するので、 配列と共用がコード上できませんので、注意が必要です。 ※ ここに紹介するコードは、AIR でも利用可能です 以下は、アイコンや画像を使用する為の埋め込み用のコードです Icon.as
// メニューバー用アイコン [Embed("_icon1.png")] private static var icon1:Class; [Embed("_icon2.png")] private static var icon2:Class; [Embed("_icon3.png")] private static var icon3:Class; // ポップアップメニュー用アイコン [Embed("_InfoBox.png")] private static var iconInfoBox:Class; [Embed("_Favorites.png")] private static var iconFavorites:Class; [Embed("_Search.png")] private static var iconSearch:Class; // 画面背景用 [Embed("_back.png")] private static var imgBack:Class; // メニューバー背景用 [Embed("_back_1.png")] private static var imgBack_1:Class; // ポップアップ・メニューバー背景用 [Embed("_menuBackSmile.png")] private static var imgMenuBackSmile:Class; // ポップアップメニューの // 動的設定用の少し大きいアイコン [Embed("_iconFire.png")] private static var iconFire:Class; // 画面上のボタン用 [Bindable] [Embed("_Button.png")] private static var iconButton:Class; 各クラスは、以下のようにインスタンス化し、画像のプロパティを取得できます // 背景画像をインスタンス化して、サイズを取得 var img:Bitmap = new imgBack_1(); e.menu.width = img.width; e.menu.height = img.height; メニュー用配列データmyMenuData1 = [ {label: "ファイル" , icon: icon1, children:[ {label: "開く", enabled: false } ,{label: "保存", userOption: "001" } ,{type: "separator" } ,{label: "オプション" , children:[ {label: "お気に入り", icon: iconFavorites } ,{label: "情報", icon: iconInfoBox } ,{label: "検索", icon: iconSearch } ]} ]} , {label: "背景処理" , icon: icon2, children:[ {label: "背景変更", type: "check", toggled: true } ,{type: "separator" } ,{label: "ここを動的に変更", type: "check", toggled: true } ]} , {label: "予備", icon: icon3 } ]; 最初、一つのデータで menuBar 用と ポップアップメニューで共用していたのですが、 動的変更のコントロールが複雑になるので、配列をコピーして使用しています。 ActionScript3.0 では、コピーは元が参照されるだけなので、 以下のようにして、配列データをコピーしてクローンを作成しています。 但し、icon データまではコピーされないので、後から設定しています var myBA:ByteArray = new ByteArray(); myBA.writeObject(myMenuData1); myBA.position = 0; myMenuData2 = myBA.readObject(); // 但し、アイコンはコピーされないので自分でコピー myMenuData2[0]["icon"] = icon1; myMenuData2[0]["children"][3]["children"][0]["icon"] = iconFavorites; myMenuData2[0]["children"][3]["children"][1]["icon"] = iconInfoBox; myMenuData2[0]["children"][3]["children"][2]["icon"] = iconSearch; myMenuData2[1]["icon"] = icon2; myMenuData2[2]["icon"] = icon3; 全体の処理コードメニューそのものの処理は、itemClick イベントで処理しますが、 見栄えの変更はいろいろ考慮する必要があります。 ● ポップアップメニュー 作成時に全体が一つのメニューなので スタイル設定を最初に適用できるのですが、実際はサブメニューも 含めて、表示されるたびにインスタンスが作成されて初期化されます。 ですから、menuShow をうまく使って変更しないと、最初に表示 されるルート部分の状態が引き継がれてしまいます。 ● メニューバー 初期状態では、menus プロパティには何も入っていません。 一度表示されて始めて格納されます。 また、initData で dataProviderにデータをセットしていますが、 Flex の特性ですぐ使用できません。 ですから、次に発生するイベントでメニューの外観の設定を行っています、 また、メニューバーでは、一度作成されたインスタンスは 継続して使用されます。ですから、ポップアップ部分の外観の設定を動的に変更可能です。 ( 厳密に言うと、menuShow イベントで毎回表示前に変える事はできます ) ※ イベントが指すメニュー itemRollOver は、マウスの下にあるメニューですが、menuShow は、 次に開かれるサブメニューを指します。この場合、サブメニューが無い場合は なにも起こりませんし、イベントの menuShow の イベントの menu プロパティは常に使用可能です。 ( マニュアルの「MenuBar アイテムがイベントを送出している場合は、null」は嘘 ) import mx.controls.*; import mx.events.*; import mx.rpc.events.*; import mx.formatters.*; import flash.external.*; import flash.events.*; include "Parts.as" // 画像の埋め込み include "Icon.as" private var myMenuData1:Array; // 配列仕立て1 private var myMenuData2:Array; // 配列仕立て2( ディープコピー先 ) private var popupMenu1:Menu; private var save:Object; // このウインドウ private var me:Application = null; // ********************************************************* // アプリケーションの初期化 // ********************************************************* public function initData():void { firebug("処理開始"); me = this; // ***************************************************** // 配列仕立てのポップアップメニュー // ***************************************************** myMenuData1 = [ {label: "ファイル" , icon: icon1, children:[ {label: "開く", enabled: false } ,{label: "保存", userOption: "001" } ,{type: "separator" } ,{label: "オプション" , children:[ {label: "お気に入り", icon: iconFavorites } ,{label: "情報", icon: iconInfoBox } ,{label: "検索", icon: iconSearch } ]} ]} , {label: "背景処理" , icon: icon2, children:[ {label: "背景変更", type: "check", toggled: true } ,{type: "separator" } ,{label: "ここを動的に変更", type: "check", toggled: true } ]} , {label: "予備", icon: icon3 } ]; popupMenu1 = Menu.createMenu( null, myMenuData1, false); // 表示する内容を対応させる popupMenu1.labelField = "label"; popupMenu1.iconField = "icon"; // イベントを登録 popupMenu1.addEventListener("itemClick", clickMenuHandler); popupMenu1.addEventListener("itemRollOver", menuItemRollOver); popupMenu1.addEventListener("menuShow", popupMenuCheck); popupMenu1.setStyle( "backgroundColor", "0x000000" ); popupMenu1.setStyle("backgroundAlpha","0.2"); popupMenu1.setStyle("backgroundImage", imgMenuBackSmile ); popupMenu1.setStyle("backgroundSize","100%"); // popupMenu1.width = 150; // ***************************************************** // menuBar 用に配列をディープコピー // 【ActionScript 3.0 のプログラミング】 // =>[配列の操作] // =>[配列のクローンの作成] // ***************************************************** var myBA:ByteArray = new ByteArray(); myBA.writeObject(myMenuData1); myBA.position = 0; myMenuData2 = myBA.readObject(); // 但し、アイコンはコピーされないので自分でコピー myMenuData2[0]["icon"] = icon1; myMenuData2[0]["children"][3]["children"][0]["icon"] = iconFavorites; myMenuData2[0]["children"][3]["children"][1]["icon"] = iconInfoBox; myMenuData2[0]["children"][3]["children"][2]["icon"] = iconSearch; myMenuData2[1]["icon"] = icon2; myMenuData2[2]["icon"] = icon3; myMenuBar.dataProvider = myMenuData2; } // ********************************************************* // creationComplete // ********************************************************* private function initApp1():void { // メニューバーのメニューは、initData では参照できないので // 見栄えをこちらで設定します var mn:Menu; // 「ファイル」メニューの設定 mn = myMenuBar.getMenuAt(0); // Alpha に使われる色 mn.setStyle("backgroundColor", "0x000000" ); mn.setStyle("backgroundAlpha","0.2"); // ぼやけて見える mn.setStyle("backgroundImage", imgMenuBackSmile ); // アイコンの背景 mn.setStyle("backgroundSize","100%"); // エリア一杯に拡大 mn.setStyle("color",0xffffff); // 「背景処理」メニューの設定 mn = myMenuBar.getMenuAt(1); // Alpha に使われる色 mn.setStyle("backgroundColor", "0x000000" ); mn.setStyle("backgroundAlpha","0.9"); // はっきり見える mn.setStyle("backgroundImage", imgBack_1 ); // 砂地の背景 mn.setStyle("backgroundSize","auto"); // そのままの大きさ } // ********************************************************* // itemClick // ********************************************************* private function clickMenuHandler(e:MenuEvent):void { // ユーザ固有のオプションのチェック if ( e.item.hasOwnProperty("userOption") ) { Alert.show(e.item.hasOwnProperty("userOption").toString()); } // menuBar の真中のメニューの背景を動的に変更する処理 // 但し、ポップアップメニューでは、 // 毎回メニューが動的に作成されているので、 // 変更しても意味が無いので処理していません if ( e.item.label == "この背景を\n変更します" ) { if ( !e.item.toggled ) { e.menu.setStyle( "backgroundColor", "0x000000" ); e.menu.setStyle("backgroundAlpha","0.2"); e.menu.setStyle("backgroundImage", imgMenuBackSmile ); e.menu.setStyle("backgroundSize","100%"); } else { e.menu.setStyle("backgroundColor", "0x000000" ); e.menu.setStyle("backgroundAlpha","0.9"); e.menu.setStyle("backgroundImage", imgBack_1 ); e.menu.setStyle("backgroundSize","auto"); } } if ( e.label == "背景変更" ) { if ( !e.item.toggled ) { save = me.getStyle("backgroundImage"); me.setStyle("backgroundImage",imgBack); // どちらか片方の状態より処理しているので、 // 両方の元データを同期させる myMenuData1[1]["children"][0]["toggled"] = false; myMenuData2[1]["children"][0]["toggled"] = false; } else { me.setStyle("backgroundImage",save); // どちらか片方の状態より処理しているので、 // 両方の元データを同期させる myMenuData1[1]["children"][0]["toggled"] = true; myMenuData2[1]["children"][0]["toggled"] = true; } } } // ********************************************************* // itemRollOver // e.menu : マウスの下のメニュー // ********************************************************* private function menuItemRollOver(e:mx.events.MenuEvent ):void { // ポップアップメニューの場合 if ( e.menu != null ) { firebug("itemRollOver:menu:"+ e.menu ); if ( e.item.label == "背景処理" ) { } } // menuBar の場合 else { firebug("itemRollOver:menu:null" ); if ( e.item.label == "背景処理" ) { myMenuData2[1]["children"][2]["label"] = "この背景を\n変更します"; myMenuData2[1]["children"][2]["icon"] = null; myMenuData2[1]["children"][2]["enabled"] = true; } } } // ********************************************************* // menuShow // サブメニューが開かれた // e.menu : 開かれたメニュー // ********************************************************* private function popupMenuCheck(e:mx.events.MenuEvent ):void { firebug("menuShow:"+ e.menu ); e.menu.setStyle("leftIconGap",0); // ポップアップメニューの場合 if ( e.menuBar == null ) { if ( e.menu.dataProvider.getItemAt(0).label == "開く" ) { e.menu.rowHeight = 24; } if ( e.menu.dataProvider.getItemAt(0).label == "お気に入り" ) { e.menu.rowHeight = 20; } if ( e.menu.dataProvider.getItemAt(0).label == "背景変更" ) { myMenuData1[1]["children"][2]["label"] = "この背景は変更不可"; myMenuData1[1]["children"][2]["icon"] = iconFire; myMenuData1[1]["children"][2]["enabled"] = false; e.menu.width = 240; } } // menuBar の場合 else { if ( e.menu.dataProvider.getItemAt(0).label == "背景変更" ) { myMenuData2[1]["children"][2]["label"] = "この背景を\n変更します"; myMenuData2[1]["children"][2]["icon"] = null; myMenuData2[1]["children"][2]["enabled"] = true; // 背景画像をインスタンス化して、サイズを取得 var img:Bitmap = new imgBack_1(); e.menu.width = img.width; e.menu.height = img.height; } } } XML 定義部分はアプリケーションでは使用していません。 アイコンが動作しないのを確認する為に使用しました。 <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" initialize="initData();" creationComplete="initApp1()" layout="absolute" > <!-- *************************************************** --> <!-- 外部ソース --> <!-- *************************************************** --> <mx:Style source="extern/Style.css" /> <mx:Script source="extern/Script.as" /> <!-- *************************************************** --> <!-- メニューバー --> <!-- *************************************************** --> <mx:MenuBar x="0" y="0" id="myMenuBar" labelField="label" iconField="icon" width="100%" fontSize="12" showRoot="false" itemRollOver="menuItemRollOver(event)" itemClick="clickMenuHandler(event)" menuShow="popupMenuCheck(event)" /> <!-- *************************************************** --> <!-- ボタン --> <!-- *************************************************** --> <mx:Button x="20" y="60" id="btn1" icon="{iconButton}" label="" styleName="orangeButton" click="popupMenu1.show(btn1.x + btn1.width, btn1.y);" /> <mx:XML format="e4x" id="myMenuDataXML"> <root> <menuitem label="ファイル" icon="icon1"> <menuitem label="開く" enabled="false"/> <menuitem label="保存" userOption="001" /> <menuitem type="separator"/> <menuitem label="オプション"> <menuitem label="お気に入り" icon="iconFavorites"/> <menuitem label="情報" icon="iconInfoBox"/> <menuitem label="検索" icon="iconSearch"/> </menuitem> </menuitem> <menuitem label="背景処理"> <menuitem label="背景変更" type="check" toggled="true" /> <menuitem type="separator"/> <menuitem label="ここを動的に変更" type="check" toggled="true" /> </menuitem> <menuitem label="予備" icon="icon3"/> </root> </mx:XML> </mx:Application> |