Flexの最初の難しい手順

少し前にFlex Builder 3を使い始めました。私は長い間プログラミングと友達でしたので、「Hello、world」、配列の並べ替え、「ボタンに沿って画像をクロールする方法」などのタスクに問題はありませんでした。 しかし、私は、外見が単純で、Flexには単純なソリューションがなかったタスクに会いました。





便宜上、それらのうち最も興味深い4つを強調しました。

  1. プロジェクトに多くのリソースを追加します。
  2. 多言語アプリケーション。
  3. モーダルウィンドウ;
  4. FlexとCSS。


タスクは難易度の高い順にリストされています。 誰かが同じ問題を簡単に(または私よりも)解決できたら嬉しいですし、コメントでこれらの解決策を説明します。



1.複数のリソースをプロジェクトに追加する



Flexプロジェクトにあらゆる種類のファイルを埋め込むのは簡単であることがすぐにわかりました。



[Embed(source="index.xml", mimeType="application/octet-stream")]

private static var index_xml : Class;



[Embed(source="picture.png")]

private static var picture_png : Class;







したがって、アプリケーションの実行時には、必要なオブジェクトを作成するだけで、ネットワークやローカルディスクからファイルをダウンロードすることなく、それらにアクセスできます。



しかし、ほとんどすぐにエラーに遭遇しました:

1067:int値の不適切なクラス型への暗黙的な変換。



次のコードでこのエラーが発生しました。



public class res {

[Embed(source="test.png")]

public static var test: Class;

public static var res_test: int;

}







判明したように、埋め込みリソースの場合、Flexは中間ASクラスを生成します。 上記の例では、クラスが生成されました:



public class res_test extends mx.core.BitmapAsset {

public function res_test() {

super();

}

}







便利なコンパイラディレクティブを使用して、この問題を把握できました: keep-generated-actionscript このディレクティブがtrueに設定されている場合 、すべての中間生成クラスのコンパイラーは、 src / generated /フォルダーにファイルを作成します。



この問題に対処して、私は次のことを考えました:どうすれば多くの埋め込みファイルを含めることができますか? 手で入力できる1つまたは2つではなく、10、20、またはそれ以上。 ヘルプも本もフォーラムも答えを出さなかった。 正直なところ、私は理解していませんでした:誰もこれをしなかったか、誰もがしましたが、彼らは黙っています。



[Embed(source =“ folder \”)] Flexのような文字列は頑固に拒否されたため、私はトリックをすることにしました。リソースでフォルダーをアーカイブします。 したがって、他のファイルと同様に、プロジェクトに含めることができるファイルを取得します。 アーカイブを操作するのはクラスライブラリ次第でした。 そのようなライブラリを見つけることは難しくありませんでした。 たとえば、 AS3 Zip LibraryまたはFZipです。



これで、アプリケーションの実行時にアーカイブから任意のファイルを使用できました。 アーカイブには、手間をかけずに好きなだけファイルを置くことができました。 すべてが正常であるようです。



しかし、ありません。 アーカイブからのファイルはByteArrayとして返されます。 テキストファイルまたはバイナリデータの場合-問題ありません。 しかし、もしこのイメージまたは、神が禁じているなら、swf、そしてタンバリンと踊り始めます。



ByteArrayをBitmapDataまたはBitmapAssetに変換することは不可能でした。 png、jpeg、swfなど、さまざまなデータ型のコンバーターすらありませんでした。 FlexにはPNGEncoder、JPEGEncoderなどがありますが、何らかの理由でPNGDecoder、JPEGDecoderはありません。



もう少し助けを探した後、Loaderクラスを見つけました。 このクラスにはloadBytes()メソッドがあります。このメソッドはByteArrayをパラメーターとして受け取り、コンテンツを自動的に認識して、目的のFlexクラスに変換します。



ダウンロード完了イベントにサブスクライブし、このコンポーネントからデータを何らかの方法で引き裂く必要性を辞めて、私は今すぐ「私を美しくする」ことを期待していました。 そこにあった。



Flex環境でこのオプションをテストしているときに、問題に気付きませんでした。 しかし、リリースして起動すると、エラーが発生しました。 その本質は次のように要約されました:ファイル"FileMyOegPrimeneniya.swf。<< 1 >> .byteArray()"にアクセスする権利がありません。 つまり、アレイにアクセスする権限がありません。 これは私に衝撃を与えました。



はい、コンパイル中にuse-networkフラグをfalseに設定しなかった場合、信頼されたゾーンに属していないか、ローカルの信頼されたサンドボックスにない、または他のいずれにも該当しない場合、アプリケーションはローカルファイルを使用できないことを理解しています-Flashプレーヤーにはセキュリティルールはありません。 しかし、自分で作成して初期化したアレイが、ローカルリソースのようなものになった理由がわかりません。これはまだローダーを介してアクセスできません!



回復して、私はさらに戦うことにしました。 次のアイデアは、Flex上にある種のアドオンを作成し、コンパイル時に[Embed(source = "folder \")]形式の行をAS3クラスに変換することでした。このフォルダーのすべてのファイルは埋め込みフラグで明示的にリストされます。 プラグインを書くのは面倒でしたが、Flexにはマクロが見つかりませんでした。 そこで私は、Eclipse環境でJavaを書いている友人に頼りました。 FlexはEclipseに基づいているため、おそらくEclipseのソリューションはFlexにも適していると考えました。



少し考えた後、友人がApache Antを勧めてくれました。 Java開発者にとっては、makeに代わるものです。 同時に、彼はファイル、フォルダー、想像力のないものを作成したり、アプリケーションを実行したり、テキストファイルを編集したりすることができます。 このユーティリティを少し掘り下げてみたところ、Flexでそれをシャープにする方法がわかりませんでした。すでに時間が足りませんでした。 そのため、Apache Antを使用するという考えを放棄し、私が望んでいたことを達成するための1つの方法(考えられる)しかありませんでした。



そして、この方法は、特定のフォルダーのAS3ファイルを生成する小さなアプリケーションを作成することでした。 このアイデアは、タスクがプロジェクトに多くのファイルを含めるようになるとすぐに現れましたが、より調和のとれた解決策があることを期待して、常に気付かないようにしました。



C ++で20分で、このAS3ファイルを生成するプログラムを作成しました。 残っている唯一の問題は、フォルダー内のリソースが変更されたときにこのプログラムを実行することを忘れないことです:)。 このプログラムは原始的であるため、ここではこのプログラムのコードを提供しません。



プロジェクトに多くのリソースを含めるという問題に対する、より有能な解決策を誰かが私に見せてくれることを今でも願っています。



2.多言語アプリケーション



ここでは、多言語アプリケーションの作成に使用した方法について説明します。 Flexには独自のローカリゼーションテクノロジーがあり、これを使用して、複数の言語をサポートするアプリケーションを作成できます。 しかし、この技術は私にとってやや不便だったので、自分の道を進むことにしました。



クラスが作成されました:



public class LanguageProvider {

private var fobj_languageData: Array = new Array();



public function Clear(): void {

fobj_languageData = new Array();

}



public function AddLanguageData(fileName : String): void {

var id : String = "";

var parent : XML = null;



for each (var item: XML in ResourcesManager.FileAsXML(fileName)..*.(hasOwnProperty("@value"))) {

id = item.name();

parent = item.parent();

while (parent != null) {

id = parent.name() + "." + id;

parent = parent.parent();

}

fobj_languageData[id] = item.@value;

}

}



public function GetStringFor(item : String): String {

var result: String = fobj_languageData[item];

if (result != null) return result; else return "<-!->";

}

}







ローカリゼーションファイルも作成されました。

<メニュー値= "メニュー">

<新しい値= "新規作成" />

<設定値= "設定">

<サウンド値= "サウンド" />

<music value = "Music" />

</ settings>

</ menu>



なぜこれが標準的な方法よりも優れているのですか:



標準的な方法よりも悪いこと:



私は究極の真実であるふりをしませんが、個人的には、私のアプローチはより便利です。 他の誰かが役に立つかもしれません。



3.モーダルウィンドウ



独自のモーダル「ウィンドウ」を作成する必要がありました。 「ウィンドウ」アラートのように。 実際には「ウィンドウ」という言葉を引用符で囲んでいます。実際には、ウィンドウではなく単なるパネルだからです。 もちろん、Alertクラスのソースコードを調べて、そこから必要なものをすべて取得しました。



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

<mx:Panel xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="400" height="300">

<mx:Script>

<![CDATA[

import mx.managers.PopUpManager;

import mx.events.CloseEvent;

import mx.core.Application;



// private

private var fbol_init: Boolean = false;

private var fobj_closeHandler: Function = null;



// protected

override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void {

super.updateDisplayList(unscaledWidth, unscaledHeight);



if (!fbol_init) {

var x:Number;

var y:Number;



if (parent == systemManager) {

x = (screen.width - width) / 2;

y = (screen.height - height) / 2;

}

else if (parent != null) {

x = (parent.width - width) / 2;

y = (parent.height - height) / 2;

}

else {

x = (Application.application.width - width) / 2;

y = (Application.application.height - height) / 2;

}



// Set my position, because my parent won't do it for me.

move(Math.round(x), Math.round(y));

fbol_init = true;

}

}



// public

public virtual function Show(closeHandler:Function = null): void {

fobj_closeHandler = closeHandler;

if (closeHandler != null) this.addEventListener(CloseEvent.CLOSE, closeHandler);

PopUpManager.addPopUp(this, Sprite(Application.application), true);



}



public virtual function Close(): void {

PopUpManager.removePopUp(this);

fbol_shown = false;

dispatchEvent(new CloseEvent(CloseEvent.CLOSE));

if (fobj_closeHandler != null) removeEventListener(CloseEvent.CLOSE, fobj_closeHandler);

}



]]>

</mx:Script>

</mx:Panel>









すべてが非常に簡単ですが、誰かが便利になることを願っています:)。



4.フレックスとCSS



FlexとCSSが友だちであることは秘密ではありません。 そして彼らはとてもフレンドリーです。 アプリケーション全体にCSSを設定し、ボタン、パネルなどの外観を決定できます。



一方、TextAreaコンポーネントがあります。 このコンポーネントには、htmlTextおよびstyleSheetプロパティがあります。 したがって、HTMLコンポーネントはこのコンポーネントに配置でき、styleSheetで指定されたスタイルを使用して表示されます。



そして今の質問は、htmlTextを表示するアプリケーションのすべてのTextAreaにCSSを設定するにはどうすればよいかということです。



アプリケーション全体にCSSを設定し、TextAreaの外観を指定すると、このコンポーネントのテキストはそのように見えるだけです。 TextAreaのHTMLテキストで使用されるクラスを記述する場合、これらのスタイルはまったく適用されません。 TextArea styleSheetプロパティはAS3からのみ利用可能であり、MXMLに対応するものがないという事実により、これはやや複雑です。



標準的な解決策が見つからないので、私は独自の解決策を考え出しました-TextAreaから継承者を作成しました。



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

<mx:TextArea xmlns:mx="http://www.adobe.com/2006/mxml"

width="100"

height="100"

creationComplete="OnCreationComplete()"

borderThickness="0"

editable="false"

horizontalScrollPolicy="off"

verticalScrollPolicy="off">



<mx:Script>

<![CDATA[

// static

private static var fobj_styleSheet : StyleSheet = null;



public static function SetStyleSheet(ss : StyleSheet):void {

fobj_styleSheet = ss;

}



// private

private function OnCreationComplete(): void {

if (fobj_styleSheet != null) this.styleSheet = fobj_styleSheet;

}

]]>

</mx:Script>

</mx:TextArea>







コードからわかるように、継承者の静的フィールドとメソッドを定義しました。 現在、アプリケーションではTextAreaではなく、相続人を使用しています。 アプリケーションコードのどこかで、CSSオブジェクトを一度ロードし、静的関数SetStyleSheetに渡します。 このクラスのすべてのオブジェクトを作成するときに、CSSを慎重に規定するようになりました。



私の経験が誰かに役立つことを願っています。



コメントと追加を事前にありがとうございます:)。



All Articles