はじめに
AIRプログラミングをしていて、ActionScript(以下AS)を使ったチュートリアルは充実していてもmxmlとASを用いたものはなかなか見つかりませんでした。僕自身プログラミング自体初心者なので、いちいち四苦八苦しています。
ということで、備忘録もかねて、mxmlとASを用いたプログラミングのチュートリアルと、ありがちな間違いについての記事を書きたいと思います。
実行環境
過去に紹介した「AIR:Eclipseでmxmlをコンパイラできる環境を一から実装」と、「AIR:Eclipseでfcsh環境を実装」を前提に、EclipseとFlex3SDKを使います。
プロラムは、undo0530さんのドラッグ&ドロップ1 外からドラッグ | FlashでAIR作りたい人の日記の最後の段落、「ファイルですねわかります」をそのまま流用させてもらいます。そちらから入手してください。
Let's Programing
まずはASだけでコンパイル
まずは先ほどのソースコードが正常にコンパイルできることを確認しましょう。ファイルを作成します。Eclipseでファイルを新規作成、ファイル名は本家が「DandDtest.as」なので、2番目ということで「DandDtest2.as」としましょう。
ソースコードを貼り付けて保存してfcsh環境を立ち上げます。
mxmlc DandDtest2.as
でコンパイル。するとエラー。
(fcsh) mxmlc DandDtest2.as fcsh: Assigned 1 as the compile target id Loading configuration file C:\flex3sdk\frameworks\flex-config.xml C:\flex\helloworld\src\DandDtest2.as: Error: A file found in a source-path 'DandDtest2' must have the same name as the class definition inside the file 'DandDtest'. (fcsh)
Javaでもそうですが、ファイル名とclass名、function名は一致させなければいけません。ファイル名は「DandDtest2.as」としたので、class名とfunction名も「DandDtest.as」にして再度コンパイル。
(fcsh) compile 1
Loading configuration file C:\flex3sdk\frameworks\flex-config.xml
Recompile: C:\flex\helloworld\src\DandDtest2.as
Reason: The source file wasn't fully compiled.
Files changed: 0 Files affected: 1
C:\flex\helloworld\src\DandDtest2.as(23): col: 36 Error: 型が見つからないか、コンパイル時定数ではありません : NativeDragEvent。
private function onDragEnter(evt:NativeDragEvent) {
^
C:\flex\helloworld\src\DandDtest2.as(30): col: 35 Error: 型が見つからないか、コンパイル時定数ではありません : NativeDragEvent。
private function onDragDrop(evt:NativeDragEvent) {
^
(fcsh)
今度もいい感じにエラー。ここで注目しなければいけないのは、元のサンプルは正しいのにもかかわらず、僕の環境ではエラーを吐いていることです。
共通しているエラー内容は、NativeDragEventが無いよ、です。しかしNativeDragEventは定義されています。それなのに間違っているのはなぜでしょうか。このNativeDragEventはFlex3SDKにAIRアプリケーション用として組み込まれています。リファレンスはこちら、NativeDragEvent - ActionScript 3.0 言語およびコンポーネントリファレンスガイドから。
これを読んでも僕は気がつかなかったわけですが、パブリック定数の項を見てください。定数の横に赤い三角のマークがありますよね。これはAIRのアプリケーションのみで使えますよ、という印です。
僕のコンパイル方法、「mxmlc DandDtest2.as」ではAIRアプリケーションではなく、Flashになってしまっています。ですからここでのコンパイルは
amxmlc DandDtest2.as
でAIRアプリケーションとしてコンパイルする必要があります。しかしfcsh環境では、デフォルトではamxmlcのコンパイルに対応していません。fcshでのamxmlcコマンドはfcshでApolloを高速コンパイル(参考リンク集のおまけ付き) | てっく煮ブログで実装方法を解説しています。今回はfcshを使わない方法でいきます。
「AIR:Eclipseでmxmlをコンパイラできる環境を一から実装」こちらの記事と同様に、Eclipseの実行>外部ツールから新たに実行プログラムを登録しましょう。
新規作成したロケーションには
C:\flex3sdk\bin\amxmlc.bat
を登録、作業ディレクトリには各人に合わせたものを、引数には
DandDtest2.as
と、コンパイルするファイルを指定してください。そしてコンパイルすると、以下のように表示されます。
Loading configuration file C:\flex3sdk\frameworks\air-config.xml
C:\flex\helloworld\src\DandDtest2.as(14): col: 25 Warning: return value for function 'init' に型宣言がありません。
private function init() {
^
C:\flex\helloworld\src\DandDtest2.as(23): col: 51 Warning: return value for function 'onDragEnter' に型宣言がありません。
private function onDragEnter(evt:NativeDragEvent) {
^
C:\flex\helloworld\src\DandDtest2.as(30): col: 50 Warning: return value for function 'onDragDrop' に型宣言がありません。
private function onDragDrop(evt:NativeDragEvent) {
^
C:\flex\helloworld\src\DandDtest2.swf (1016 bytes)
Eclipseでは、このメッセージが赤色で表示されます。Errorは出ていませんが、Warningが出ています。見えにくいので、型宣言を忘れないようにすると、気持ち間違えにくいプログラミングが出来ると思います。それぞれの()のあとに「:void」をつけてコンパイル。
Loading configuration file C:\flex3sdk\frameworks\air-config.xml C:\flex\helloworld\src\DandDtest2.swf (1027 bytes)
コンパイル成功。しかしこれでは実行できません。出力されたファイルを実行すると、
VerifyError: Error #1014: クラス flash.events::NativeDragEvent が見つかりません。 at global$init()
amxmlcコマンドでコンパイルして出力されるswfファイルは、AIRアプリケーションのための中間段階のファイルです。実際に実行するためにはAIRアプリケーションとしてパッケージングしなければいけません。
とはいっても、いちいち動作確認の度にやるのは馬鹿らしい話です。そこで登場するのがadlコマンドです。これはデバッグ用のコマンドで、一度そのプログラムに対応させたものを作成しておけば、amxmlcコマンドで中間ファイルとして出力されたswfを実際のアプリケーションとして動作させることができます。
新しいファイルを作成し、それの名前を「DandDtest2.xml」としてください。そしてファイルの中身を、
<?xml version="1.0" encoding="utf-8" ?> <application xmlns="http://ns.adobe.com/air/application/1.0" minimumPatchLevel="1047"> <id>net.libertatem.org.DandDtest2</id> <name>DandDtest2</name> <version>1.0</version> <filename>DandDtest2</filename> <description>DandDtest2 application</description> <copyright>(c) 2008 Libertas</copyright> <initialWindow> <content>DandDtest2.swf</content> <title>DandDtest2</title> <systemChrome>standard</systemChrome> <transparent>false</transparent> <visible>true</visible> <minimizable>true</minimizable> <maximizable>true</maximizable> <resizable>true</resizable> <x>150</x> <y>150</y> </initialWindow> <installFolder>libertas/DandDtest2</installFolder> <programMenuFolder>libertas/DandDtest2.as</programMenuFolder> <customUpdateUI>false</customUpdateUI> <allowBrowserInvocation>false</allowBrowserInvocation> </application>
コピペして保存。このファイルは詳しい説明は省略します。adfファイルというもので、プログラムのウィンドウサイズなどを指定しています。DandDtest2.swfが中段で指定されているところに注目してください。
それではまたEclipseの実行>外部ツールから新たに実行プログラムを登録しましょう。新規作成したロケーションには
C:\flex3sdk\bin\adl.exe
を登録、作業ディレクトリには各人に合わせたものを、引数には
DandDtest2.xml
としてLet's実行です。そうするとウィンドウが現れましたね。この白い四角になにかファイルをドラック&ドロップしてみてください。そうするとEclipseのコンソールウィンドウに文字が現れました。traceは本来デバッグなどに使用する出力コマンドです。僕の環境では文字化けしてしまっていますが、"ファイルですね、わかります"と出力されているはずです。
AS+mxmlでコンパイル
やっとmxmlです。それではmxmlファイルを「DandDtest2.mxml」で新しく作成してください。そして以下をコピぺ。
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:Script source="DandDtest2.as" /> </mx:Application>
さて、これでmxmlからASを呼び出しています。実行できるはず......!と、その前に、amxmlcコマンドの対象を新たなファイルにするために、引数の値を書き換えておきましょう。「DandDtest2.as」から「DandDtest2.mxml」です。
Loading configuration file C:\flex3sdk\frameworks\air-config.xml
C:\flex\helloworld\src\DandDtest2.as(1): col: 9 Error: パッケージをネストすることはできません。
package {
^
Why何故......。ではここでは何も考えずに消してみましょう。出来ないなら消せばいい。「DandDtest2.as」のpackageを{}と一緒に消しましょう。これでどうだとコンパイル。
Loading configuration file C:\flex3sdk\frameworks\air-config.xml
C:\flex\helloworld\src\DandDtest2.as(6): col: 9 Error: クラスをネストすることはできません。
public class DandDtest2 extends Sprite {
^
shit何故......。不安なんか気にせずに消してみましょう。出来ないなら消せばいい。「DandDtest2.as」のclassの行を{}と一緒に消しましょう。これでどうだとコンパイル。
Loading configuration file C:\flex3sdk\frameworks\air-config.xml
C:\flex\helloworld\src\DandDtest2.as(10): col: 20: Error: Multiple constructor definitions found. Constructor may not be defined in <Script/> code.
public function DandDtest2() {
^
......もう言わなくてもわかりますね。消し消し~。
Loading configuration file C:\flex3sdk\frameworks\air-config.xml C:\flex\helloworld\src\DandDtest2.swf (157260 bytes)
やった!コンパイルは成功です!
何でネストできないの?
さまざまな記事で触れられていますが、mxmlからASを呼び出したときは、既にpackageとclassは呼び出されています。ですからファイルにも書かれていると二重に呼び出されたことになります。そのために消す必要があります。
これは仕様ですので今後気をつけてください。ASの書き始めは見た目C言語のようになる、ということです。
完成したかな?
ここまでのASがどうなっているかを下に示します。
import flash.desktop.*;
import flash.display.*;
import flash.events.*;
private var Yohaku:Number = 20;
private var canvas:Sprite = new Sprite();
init();
private function init():void {
canvas.graphics.beginFill(0xeeeeee);
canvas.graphics.drawRect(Yohaku,Yohaku,stage.stageWidth - Yohaku*2, stage.stageHeight - Yohaku*2);
canvas.graphics.endFill();
addChild(canvas);
canvas.addEventListener(NativeDragEvent.NATIVE_DRAG_ENTER,onDragEnter);
canvas.addEventListener(NativeDragEvent.NATIVE_DRAG_DROP,onDragDrop);
}
private function onDragEnter(evt:NativeDragEvent):void {
var data:Clipboard = evt.clipboard;
if (data.hasFormat(ClipboardFormats.FILE_LIST_FORMAT)) {
NativeDragManager.acceptDragDrop(canvas);
}
}
private function onDragDrop(evt:NativeDragEvent):void {
trace("ファイルですね、わかります");
}
adlを呼び出しましょう。コンパイルが成功するはずです。
やった~コンパイル成功。でも、あれ、白い四角が表示されていない?
AS+mxmlでのプログラミングで間違いやすいポイント
継承
AIRアプリケーションではUIComponentはSpriteを継承しているためです。これの取り組みについてはこちらの記事に詳しく書かれています。Flex 3で直接Spriteを使用することはできない? - Memorize -
この行に注目してください。
private var canvas:Sprite = new Sprite();
ここでSpriteが使われていますね。これを以下のようにします。
private var canvas:UIComponent = new UIComponent();
このように定義が変わっていることがあります。コンパイルが通っても正常動作するとは限らないので用心してください。
mx.core
AIRアプリケーションとして、インポートをいつも求められるのがこれです。先頭行に追加してください。
import mx.core.*;
必ず書くぐらいの認識で問題ないです。
mxmlから呼び出そう
さて、本来のASで以下の部分がありましたね。
public function DandDtest() {
init();
}
ここから「init()」を呼び出していましたが、先ほど消してしまったので機能していません。ですから残された「init()」も消してしまいましょう。
変わりにmxmlから呼び出す必要があります。次の要素を「mx:Application」タグ内に定義してください。
applicationComplete="init();"
これで完成です。
完成!出来上がった3つのファイル
完成しました!いや、記述ミスがあったら完成していないかもしれません。困ったね。
完成したファイルは以下のようになります。
DandDtest2.mxml
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" applicationComplete="init();" layout="absolute"> <mx:Script source="DandDtest2.as" /> </mx:Application>
DandDtest2.as
import mx.core.*;
import flash.desktop.*;
import flash.display.*;
import flash.events.*;
private var Yohaku:Number = 20;
private var canvas:UIComponent = new UIComponent();
private function init():void {
canvas.graphics.beginFill(0xeeeeee);
canvas.graphics.drawRect(Yohaku,Yohaku,stage.stageWidth - Yohaku*2, stage.stageHeight - Yohaku*2);
canvas.graphics.endFill();
addChild(canvas);
canvas.addEventListener(NativeDragEvent.NATIVE_DRAG_ENTER,onDragEnter);
canvas.addEventListener(NativeDragEvent.NATIVE_DRAG_DROP,onDragDrop);
}
private function onDragEnter(evt:NativeDragEvent):void {
var data:Clipboard = evt.clipboard;
if (data.hasFormat(ClipboardFormats.FILE_LIST_FORMAT)) {
NativeDragManager.acceptDragDrop(canvas);
}
}
private function onDragDrop(evt:NativeDragEvent):void {
trace("ファイルですね、わかります");
}
DandDtest2.xml
<?xml version="1.0" encoding="utf-8" ?> <application xmlns="http://ns.adobe.com/air/application/1.0" minimumPatchLevel="1047"> <id>net.libertatem.org.DandDtest2</id> <name>DandDtest2</name> <version>1.0</version> <filename>DandDtest2</filename> <description>DandDtest2 application</description> <copyright>(c) 2008 Libertas</copyright> <initialWindow> <content>DandDtest2.swf</content> <title>DandDtest2</title> <systemChrome>standard</systemChrome> <transparent>false</transparent> <visible>true</visible> <minimizable>true</minimizable> <maximizable>true</maximizable> <resizable>true</resizable> <x>150</x> <y>150</y> </initialWindow> <installFolder>libertas/DandDtest2</installFolder> <programMenuFolder>libertas/DandDtest2.as</programMenuFolder> <customUpdateUI>false</customUpdateUI> <allowBrowserInvocation>false</allowBrowserInvocation> </application> </pre>
あとがき
用語とか高確率で間違っていると思います。調べながらやってみましたが、そのかわり初心者の僕らしいチュートリアルにするべく、慣れていない人には気になるポイントを重点的に取り上げてみました。誰かに聞けないとめちゃくちゃ解決に時間かかりますからね......
記述ミスの確認もしましたが、何かありましたらコメントお願いします。
