ブラウザでダウンロード メニューのアイコンについて2008/11/22 時点の 3.1.0 build 2710 において、XML でメニュー処理すると アイコンが使用できません。 iconFunction プロパティを使用すると、表示はされますが( 機能は正常 ) アイテム毎のコントロールができません。明らかにバグです。 それでも、アイコンを使用しなければ XML を使用できるので、それはそれで 良いのですが、プロパティの参照に XML 仕様の "@" を使用するので、 配列と共用がコード上できませんので、注意が必要です。 ※ ここに紹介するコードは、AIR でも利用可能です 以下は、アイコンや画像を使用する為の埋め込み用のコードです Icon.as
01. // メニューバー用アイコン 02. [Embed( "_icon1.png" )] 03. private static var icon1:Class; 04. [Embed( "_icon2.png" )] 05. private static var icon2:Class; 06. [Embed( "_icon3.png" )] 07. private static var icon3:Class; 08. 09. // ポップアップメニュー用アイコン 10. [Embed( "_InfoBox.png" )] 11. private static var iconInfoBox:Class; 12. [Embed( "_Favorites.png" )] 13. private static var iconFavorites:Class; 14. [Embed( "_Search.png" )] 15. private static var iconSearch:Class; 16. 17. // 画面背景用 18. [Embed( "_back.png" )] 19. private static var imgBack:Class; 20. // メニューバー背景用 21. [Embed( "_back_1.png" )] 22. private static var imgBack_1:Class; 23. // ポップアップ・メニューバー背景用 24. [Embed( "_menuBackSmile.png" )] 25. private static var imgMenuBackSmile:Class; 26. 27. // ポップアップメニューの 28. // 動的設定用の少し大きいアイコン 29. [Embed( "_iconFire.png" )] 30. private static var iconFire:Class; 31. 32. // 画面上のボタン用 33. [Bindable] 34. [Embed( "_Button.png" )] 35. private static var iconButton:Class; 各クラスは、以下のようにインスタンス化し、画像のプロパティを取得できます 1. // 背景画像をインスタンス化して、サイズを取得 2. var img:Bitmap = new imgBack_1(); 3. e.menu.width = img.width; 4. e.menu.height = img.height; メニュー用配列データ01. myMenuData1 = 02. [ 03. {label: "ファイル" , icon: icon1, children:[ 04. {label: "開く" , enabled: false } 05. ,{label: "保存" , userOption: "001" } 06. ,{type: "separator" } 07. ,{label: "オプション" , children:[ 08. {label: "お気に入り" , icon: iconFavorites } 09. ,{label: "情報" , icon: iconInfoBox } 10. ,{label: "検索" , icon: iconSearch } 11. ]} 12. ]} 13. , 14. {label: "背景処理" , icon: icon2, children:[ 15. {label: "背景変更" , type: "check" , toggled: true } 16. ,{type: "separator" } 17. ,{label: "ここを動的に変更" , type: "check" , toggled: true } 18. ]} 19. , 20. {label: "予備" , icon: icon3 } 21. ]; 最初、一つのデータで menuBar 用と ポップアップメニューで共用していたのですが、 動的変更のコントロールが複雑になるので、配列をコピーして使用しています。 ActionScript3.0 では、コピーは元が参照されるだけなので、 以下のようにして、配列データをコピーしてクローンを作成しています。 但し、icon データまではコピーされないので、後から設定しています 01. var myBA:ByteArray = new ByteArray(); 02. myBA.writeObject(myMenuData1); 03. myBA.position = 0 ; 04. myMenuData2 = myBA.readObject(); 05. // 但し、アイコンはコピーされないので自分でコピー 06. myMenuData2[ 0 ][ "icon" ] = icon1; 07. myMenuData2[ 0 ][ "children" ][ 3 ][ "children" ][ 0 ][ "icon" ] = iconFavorites; 08. myMenuData2[ 0 ][ "children" ][ 3 ][ "children" ][ 1 ][ "icon" ] = iconInfoBox; 09. myMenuData2[ 0 ][ "children" ][ 3 ][ "children" ][ 2 ][ "icon" ] = iconSearch; 10. myMenuData2[ 1 ][ "icon" ] = icon2; 11. myMenuData2[ 2 ][ "icon" ] = icon3; 全体の処理コードメニューそのものの処理は、itemClick イベントで処理しますが、 見栄えの変更はいろいろ考慮する必要があります。 ● ポップアップメニュー 作成時に全体が一つのメニューなので スタイル設定を最初に適用できるのですが、実際はサブメニューも 含めて、表示されるたびにインスタンスが作成されて初期化されます。 ですから、menuShow をうまく使って変更しないと、最初に表示 されるルート部分の状態が引き継がれてしまいます。 ● メニューバー 初期状態では、menus プロパティには何も入っていません。 一度表示されて始めて格納されます。 また、initData で dataProviderにデータをセットしていますが、 Flex の特性ですぐ使用できません。 ですから、次に発生するイベントでメニューの外観の設定を行っています、 また、メニューバーでは、一度作成されたインスタンスは 継続して使用されます。ですから、ポップアップ部分の外観の設定を動的に変更可能です。 ( 厳密に言うと、menuShow イベントで毎回表示前に変える事はできます ) ※ イベントが指すメニュー itemRollOver は、マウスの下にあるメニューですが、menuShow は、 次に開かれるサブメニューを指します。この場合、サブメニューが無い場合は なにも起こりませんし、イベントの menuShow の イベントの menu プロパティは常に使用可能です。 ( マニュアルの「MenuBar アイテムがイベントを送出している場合は、null」は嘘 ) ![]() ![]() ![]() 001. import mx.controls.*; 002. import mx.events.*; 003. import mx.rpc.events.*; 004. import mx.formatters.*; 005. import flash.external.*; 006. import flash.events.*; 007. 008. include "Parts.as" 009. // 画像の埋め込み 010. include "Icon.as" 011. 012. private var myMenuData1:Array; // 配列仕立て1 013. private var myMenuData2:Array; // 配列仕立て2( ディープコピー先 ) 014. private var popupMenu1:Menu; 015. private var save:Object; 016. 017. // このウインドウ 018. private var me:Application = null ; 019. 020. // ********************************************************* 021. // アプリケーションの初期化 022. // ********************************************************* 023. public function initData(): void { 024. 025. firebug( "処理開始" ); 026. 027. me = this ; 028. 029. // ***************************************************** 030. // 配列仕立てのポップアップメニュー 031. // ***************************************************** 032. myMenuData1 = 033. [ 034. {label: "ファイル" , icon: icon1, children:[ 035. {label: "開く" , enabled: false } 036. ,{label: "保存" , userOption: "001" } 037. ,{type: "separator" } 038. ,{label: "オプション" , children:[ 039. {label: "お気に入り" , icon: iconFavorites } 040. ,{label: "情報" , icon: iconInfoBox } 041. ,{label: "検索" , icon: iconSearch } 042. ]} 043. ]} 044. , 045. {label: "背景処理" , icon: icon2, children:[ 046. {label: "背景変更" , type: "check" , toggled: true } 047. ,{type: "separator" } 048. ,{label: "ここを動的に変更" , type: "check" , toggled: true } 049. ]} 050. , 051. {label: "予備" , icon: icon3 } 052. ]; 053. 054. popupMenu1 = Menu.createMenu( null , myMenuData1, false ); 055. // 表示する内容を対応させる 056. popupMenu1.labelField = "label" ; 057. popupMenu1.iconField = "icon" ; 058. // イベントを登録 059. popupMenu1.addEventListener( "itemClick" , clickMenuHandler); 060. popupMenu1.addEventListener( "itemRollOver" , menuItemRollOver); 061. popupMenu1.addEventListener( "menuShow" , popupMenuCheck); 062. 063. popupMenu1.setStyle( "backgroundColor" , "0x000000" ); 064. popupMenu1.setStyle( "backgroundAlpha" , "0.2" ); 065. popupMenu1.setStyle( "backgroundImage" , imgMenuBackSmile ); 066. popupMenu1.setStyle( "backgroundSize" , "100%" ); 067. // popupMenu1.width = 150; 068. 069. // ***************************************************** 070. // menuBar 用に配列をディープコピー 071. // 【ActionScript 3.0 のプログラミング】 072. // =>[配列の操作] 073. // =>[配列のクローンの作成] 074. // ***************************************************** 075. var myBA:ByteArray = new ByteArray(); 076. myBA.writeObject(myMenuData1); 077. myBA.position = 0 ; 078. myMenuData2 = myBA.readObject(); 079. // 但し、アイコンはコピーされないので自分でコピー 080. myMenuData2[ 0 ][ "icon" ] = icon1; 081. myMenuData2[ 0 ][ "children" ][ 3 ][ "children" ][ 0 ][ "icon" ] = iconFavorites; 082. myMenuData2[ 0 ][ "children" ][ 3 ][ "children" ][ 1 ][ "icon" ] = iconInfoBox; 083. myMenuData2[ 0 ][ "children" ][ 3 ][ "children" ][ 2 ][ "icon" ] = iconSearch; 084. myMenuData2[ 1 ][ "icon" ] = icon2; 085. myMenuData2[ 2 ][ "icon" ] = icon3; 086. 087. myMenuBar.dataProvider = myMenuData2; 088. } 089. 090. // ********************************************************* 091. // creationComplete 092. // ********************************************************* 093. private function initApp1(): void { 094. 095. // メニューバーのメニューは、initData では参照できないので 096. // 見栄えをこちらで設定します 097. var mn:Menu; 098. 099. // 「ファイル」メニューの設定 100. mn = myMenuBar.getMenuAt( 0 ); 101. // Alpha に使われる色 102. mn.setStyle( "backgroundColor" , "0x000000" ); 103. mn.setStyle( "backgroundAlpha" , "0.2" ); // ぼやけて見える 104. mn.setStyle( "backgroundImage" , imgMenuBackSmile ); // アイコンの背景 105. mn.setStyle( "backgroundSize" , "100%" ); // エリア一杯に拡大 106. mn.setStyle( "color" , 0xffffff ); 107. 108. // 「背景処理」メニューの設定 109. mn = myMenuBar.getMenuAt( 1 ); 110. // Alpha に使われる色 111. mn.setStyle( "backgroundColor" , "0x000000" ); 112. mn.setStyle( "backgroundAlpha" , "0.9" ); // はっきり見える 113. mn.setStyle( "backgroundImage" , imgBack_1 ); // 砂地の背景 114. mn.setStyle( "backgroundSize" , "auto" ); // そのままの大きさ 115. 116. } 117. 118. // ********************************************************* 119. // itemClick 120. // ********************************************************* 121. private function clickMenuHandler(e:MenuEvent): void { 122. 123. // ユーザ固有のオプションのチェック 124. if ( e.item.hasOwnProperty( "userOption" ) ) { 125. Alert.show(e.item.hasOwnProperty( "userOption" ).toString()); 126. } 127. 128. // menuBar の真中のメニューの背景を動的に変更する処理 129. // 但し、ポップアップメニューでは、 130. // 毎回メニューが動的に作成されているので、 131. // 変更しても意味が無いので処理していません 132. if ( e.item.label == "この背景を\n変更します" ) { 133. if ( !e.item.toggled ) { 134. e.menu.setStyle( "backgroundColor" , "0x000000" ); 135. e.menu.setStyle( "backgroundAlpha" , "0.2" ); 136. e.menu.setStyle( "backgroundImage" , imgMenuBackSmile ); 137. e.menu.setStyle( "backgroundSize" , "100%" ); 138. } 139. else { 140. e.menu.setStyle( "backgroundColor" , "0x000000" ); 141. e.menu.setStyle( "backgroundAlpha" , "0.9" ); 142. e.menu.setStyle( "backgroundImage" , imgBack_1 ); 143. e.menu.setStyle( "backgroundSize" , "auto" ); 144. } 145. } 146. 147. if ( e.label == "背景変更" ) { 148. if ( !e.item.toggled ) { 149. save = me.getStyle( "backgroundImage" ); 150. me.setStyle( "backgroundImage" ,imgBack); 151. // どちらか片方の状態より処理しているので、 152. // 両方の元データを同期させる 153. myMenuData1[ 1 ][ "children" ][ 0 ][ "toggled" ] = false ; 154. myMenuData2[ 1 ][ "children" ][ 0 ][ "toggled" ] = false ; 155. } 156. else { 157. me.setStyle( "backgroundImage" ,save); 158. // どちらか片方の状態より処理しているので、 159. // 両方の元データを同期させる 160. myMenuData1[ 1 ][ "children" ][ 0 ][ "toggled" ] = true ; 161. myMenuData2[ 1 ][ "children" ][ 0 ][ "toggled" ] = true ; 162. } 163. } 164. 165. } 166. 167. // ********************************************************* 168. // itemRollOver 169. // e.menu : マウスの下のメニュー 170. // ********************************************************* 171. private function menuItemRollOver(e:mx.events.MenuEvent ): void { 172. 173. 174. // ポップアップメニューの場合 175. if ( e.menu != null ) { 176. firebug( "itemRollOver:menu:" + e.menu ); 177. if ( e.item.label == "背景処理" ) { 178. } 179. } 180. // menuBar の場合 181. else { 182. firebug( "itemRollOver:menu:null" ); 183. if ( e.item.label == "背景処理" ) { 184. myMenuData2[ 1 ][ "children" ][ 2 ][ "label" ] = "この背景を\n変更します" ; 185. myMenuData2[ 1 ][ "children" ][ 2 ][ "icon" ] = null ; 186. myMenuData2[ 1 ][ "children" ][ 2 ][ "enabled" ] = true ; 187. } 188. } 189. 190. 191. } 192. 193. // ********************************************************* 194. // menuShow 195. // サブメニューが開かれた 196. // e.menu : 開かれたメニュー 197. // ********************************************************* 198. private function popupMenuCheck(e:mx.events.MenuEvent ): void { 199. 200. firebug( "menuShow:" + e.menu ); 201. 202. e.menu.setStyle( "leftIconGap" , 0 ); 203. 204. // ポップアップメニューの場合 205. if ( e.menuBar == null ) { 206. if ( e.menu.dataProvider.getItemAt( 0 ).label == "開く" ) { 207. e.menu.rowHeight = 24 ; 208. } 209. if ( e.menu.dataProvider.getItemAt( 0 ).label == "お気に入り" ) { 210. e.menu.rowHeight = 20 ; 211. } 212. if ( e.menu.dataProvider.getItemAt( 0 ).label == "背景変更" ) { 213. myMenuData1[ 1 ][ "children" ][ 2 ][ "label" ] = "この背景は変更不可" ; 214. myMenuData1[ 1 ][ "children" ][ 2 ][ "icon" ] = iconFire; 215. myMenuData1[ 1 ][ "children" ][ 2 ][ "enabled" ] = false ; 216. e.menu.width = 240 ; 217. } 218. } 219. // menuBar の場合 220. else { 221. if ( e.menu.dataProvider.getItemAt( 0 ).label == "背景変更" ) { 222. myMenuData2[ 1 ][ "children" ][ 2 ][ "label" ] = "この背景を\n変更します" ; 223. myMenuData2[ 1 ][ "children" ][ 2 ][ "icon" ] = null ; 224. myMenuData2[ 1 ][ "children" ][ 2 ][ "enabled" ] = true ; 225. // 背景画像をインスタンス化して、サイズを取得 226. var img:Bitmap = new imgBack_1(); 227. e.menu.width = img.width; 228. e.menu.height = img.height; 229. } 230. } 231. 232. 233. } XML 定義部分はアプリケーションでは使用していません。 アイコンが動作しないのを確認する為に使用しました。 01. <?xml version= "1.0" encoding= "utf-8" ?> 02. <mx:Application 03. xmlns:mx= "http://www.adobe.com/2006/mxml" 04. initialize= "initData();" 05. creationComplete= "initApp1()" 06. layout= "absolute" 07. > 08. 09. <!-- *************************************************** --> 10. <!-- 外部ソース --> 11. <!-- *************************************************** --> 12. <mx:Style source= "extern/Style.css" /> 13. <mx:Script source= "extern/Script.as" /> 14. 15. <!-- *************************************************** --> 16. <!-- メニューバー --> 17. <!-- *************************************************** --> 18. <mx:MenuBar 19. x= "0" y= "0" 20. id= "myMenuBar" 21. labelField= "label" 22. iconField= "icon" 23. width= "100%" 24. fontSize= "12" 25. showRoot= "false" 26. itemRollOver= "menuItemRollOver(event)" 27. itemClick= "clickMenuHandler(event)" 28. menuShow= "popupMenuCheck(event)" 29. /> 30. 31. <!-- *************************************************** --> 32. <!-- ボタン --> 33. <!-- *************************************************** --> 34. <mx:Button 35. x= "20" y= "60" 36. id= "btn1" 37. icon= "{iconButton}" 38. label= "" 39. styleName= "orangeButton" 40. click= "popupMenu1.show(btn1.x + btn1.width, btn1.y);" 41. /> 42. 43. <mx:XML format= "e4x" id= "myMenuDataXML" > 44. <root> 45. <menuitem label= "ファイル" icon= "icon1" > 46. <menuitem label= "開く" enabled= "false" /> 47. <menuitem label= "保存" userOption= "001" /> 48. <menuitem type= "separator" /> 49. <menuitem label= "オプション" > 50. <menuitem label= "お気に入り" icon= "iconFavorites" /> 51. <menuitem label= "情報" icon= "iconInfoBox" /> 52. <menuitem label= "検索" icon= "iconSearch" /> 53. </menuitem> 54. </menuitem> 55. <menuitem label= "背景処理" > 56. <menuitem label= "背景変更" type= "check" toggled= "true" /> 57. <menuitem type= "separator" /> 58. <menuitem label= "ここを動的に変更" type= "check" toggled= "true" /> 59. </menuitem> 60. <menuitem label= "予備" icon= "icon3" /> 61. </root> 62. </mx:XML> 63. 64. </mx:Application> |