JavaFX Support

awk4j (AWK for Java Platform)

JavaFX サポートとは

'07年春、 リッチ・インターネット・アプリケーション (RIA) 向けソフトウエア・プラットフォーム としてデビューした JavaFX™ は、 '08年12月、 JavaFXの正式版 SDK が公開された。 JavaFX の新言語仕様をサポートした awk4j により、 AWKスクリプト と JavaFX による マルチリンガル環境での新しいスクリプティングの世界を体験ください。

さあ始めよう

#% で始まるコメント部分は、ホストスクリプトの埋め込み指定で JavaFXスクリプトをそのまま記述する。 (C言語: asm(), JSP: <%%>に相当)

Note: この技は他のHOST言語を使用する場合も利用可能。

サンプル 1 (簡易ブラウザ)

“世界最短 1文字スクリプト '1' でホームページにアクセス” で紹介したスクリプトの GUI 版。
Label コンポーネントは、 HTMLタグを受け付けるため、 SwingLabel で未サポートのタグを削除して表示する。

« サンプル: Browser2.awk »
#% import javafx.stage.Stage;
#% import javafx.scene.Scene;
#% import javafx.ext.swing.*;

    { basename = FILENAME; result = result $0
}
END { IGNORECASE = 1
    gsub(/<(!|meta)[^>]+>/, "", result); sub(/^.*<html[^>]+>/, "<html>", result)
    sub(/<head>/, "<head><base href='" basename "' />", result)
#%  Stage {
#%    scene: Scene { content:
#%      SwingScrollPane { height: 640 width: 560
#%        view: SwingLabel { text: result as String}
#%      }
#%    }
#%  }

}

Note: JavaFX は静的型付き言語のため、 JavaFX でAWK 変数を使用する場合は明示的な型変換(キャスト)が必要 (awk4j 変数は Object 宣言されており型は無い)。

サンプル 2 (月齢計算)

月齢計算 (unix ツール pom) サンプルの GUI 版。 月齢を ProgressBar コンポーネントで表示、 GNU AWK で動かせばコンソールアプリ としてそのまま動作する。

« サンプル: Pom2.awk (GUI部のみ掲載) »
#% import javafx.stage.Stage;
#% import javafx.scene.Scene;
#% import javafx.ext.swing.*;

    :
  { if (sub(/.*<IMG SRC=\"/, "")) {
        baseurl = FILENAME; sub(/[^\/]+\.html$/, "", baseurl)
        sub(/\".*$/, ""); imageurl = $0
        exit(0)
    }
}
END { imghtml = "<html><body link='cyan' vlink='cyan' style='background-color: black; " \
    "width: 640px; height: 480px; background-image: url(" baseurl imageurl \
    ");'><h3><a href='" FILENAME "'>" result "</a></h3></body></html>"
#%  Stage { width: 640 height: 480
#%    scene: Scene { content: SwingLabel { text: imghtml as String }
#%    }
#%  }

}

Note: 処理内容は Android サポートと同じだが、残念ながらリンクをクリックしても何もおきない (^^)!

サンプル 3 (素数を求める)

素数を求めるサンプルの GUI 版。 GNU AWK で動かせばコンソールアプリとしてそのまま動作する。

« サンプル: PrimeNumber2.awk »
#% import javafx.stage.Stage;
#% import javafx.scene.Scene;
#% import javafx.scene.text.*;
#% import javafx.ext.swing.*;

BEGIN  {
    number = int(ARGV[1])    # 求める素数の最大値
    result = number " までの素数:" prime(number)
    print result
#%  var textField = SwingTextField { columns: 8, text: "{number}" };
#%  Stage {
#%    scene: Scene { content: [
#%      textField,
#%      SwingButton { text: "再計算" translateX: 100
#%        action: function() { number = textField.text;
#%          result = "{number} までの素数:{prime([number])}";
#%        }
#%      },
#%      Text { content: bind result as String y: 40 wrappingWidth: 250
#%      }
#%    ]}
#%  }

}
function isPrime(n,  i) {
    if (n < 2) return 0
    if (n == 2) return 1
    if (n%2 == 0) return 0
    for (i = 3; i*i <= n; i+=2)
      if (n%i == 0) return 0
    return 1
}
function prime(n,  i, s) {
    n -= 0    # 数値化
    for (i = 2; i <= n; i++)
      if (0 != isPrime(i)) s = s " " i
    return s
}

Note: bind 機能により Text に計算結果をの自動反映させている。

サンプル 4 (RSS閲覧)

インターネットにアクセスして RSS を閲覧の GUI 版。 XMLタグを強引にハンドリング、広告記事を削除して整形出力する。

« サンプル: News2.awk »
#% import javafx.stage.Stage;
#% import javafx.scene.Scene;
#% import javafx.scene.text.*;
#% import javafx.ext.swing.*;

BEGIN { result = ""; RS="</[^>]+>"  # XMLの終了タグ</?>をセパレータとして入力
}
    { gsub(/\n+/,"") }
/<title>/ {
    sub(/^.+>/, ""); title = $0; if ("" != $0) { result = result $0 "\n"; print } }
/<description>/ && "" != title {
    gsub(/^.+>|&lt;.+/, ""); result = result $0 "\n\n"; print $0 "\n" }
END {
#%  var textArea = new javax.swing.JTextArea(result as String, 45, 42);
#%  textArea.setLineWrap(true);
#%  Stage {
#%    scene: Scene { content:
#%      SwingScrollPane { view: SwingScrollPane.wrap(textArea)
#%    }
#%  }
}

Note: テキストをワードラップするために swing の JTextArea を使用したサンプル。

サンプル 5 (マンデルブロ集合)

複数言語連携 (AWK, Java, JAVAFX) でマンデルブロ集合に挑戦 (エンジンは、Java Imageオブジェクトで実装)。 面倒な GUI を手軽に記述できるところが JavaFX のポイント。

« サンプル: SimpleMandel2.awk (イメージ部のみの簡易版) »
#% import javafx.scene.image.*;
#% import javafx.scene.input.*;
#% import javafx.scene.Scene;
#% import javafx.stage.Stage;
#% import mandel.MandelEngine;
#% var engine: MandelEngine;
#% var imagex: Image;
#% var mouseButton: MouseButton;

BEGIN  {
    CONVFMT = "%.18g"; CIMG_WIDTH = 320; CIMG_HEIGHT = CIMG_WIDTH / 4 * 3
    X = -1.94155844996; Y = 0.00011276997004344; W = 0.0000001
    HUE = 0; SAT = .4; GRA = .01; ITE = 1024
    #%  engine = new MandelEngine(CIMG_WIDTH, CIMG_HEIGHT);
    #%  imagex = Image.fromBufferedImage(engine);
    palette(); calculate();
#%  Stage { title: "awk4j - Mandelbrot (FX)"
#%    resizable: false
#%    scene: Scene { content:
#%      ImageView { image: bind imagex
#%        onMousePressed: function(e: MouseEvent) { zoom([e.x, e.y, e.shiftDown, e.button]); }
#%        onMouseDragged: function(e: MouseEvent) { zoom([e.x, e.y, e.shiftDown, e.button]); }
#%      }
#%    }
#%  }

}
function palette() {
    #%  engine.setPalette(HUE, SAT, GRA, ITE);
}
function calculate() {
    #%  engine.calculate(X, Y, W, ITE);
    #%  imagex = Image.fromBufferedImage(engine);

}
function zoom(x, y, isShiftDown, button,  b) {
    if (isShiftDown) {                # シフト+クリック:中心座標移動
        X = (X + (x - CIMG_WIDTH / 2) * W / CIMG_WIDTH)
        Y = (Y - (y - CIMG_HEIGHT / 2) * W / CIMG_WIDTH)
    } else {
    #%  if (MouseButton.NONE != button) mouseButton = button as MouseButton;
    #%  b = (MouseButton.PRIMARY == mouseButton);

        W = (b) ? W / 1.5 : W * 1.5   # ドラッグ:拡大, 右ボタンドラッグ:縮小
    }
    calculate()
}

Note: 先頭部分で、クラス変数 (var) を定義、 AWK 関数 (zoom) 呼び出しは、 引数を列 ([ ]) で指定する。

Note: Model:Java, View:JavaFX, Controller:AWK といった利用も有りか (^^)!

コマンドリファレンス

AWKスクリプトを JavaFX クラスにコンパイルし実行するためには、以下のコマンドを使用する。

  1. AWKスクリプトを JavaFXスクリプトへ変換
    ${JAVA} [java-options] org.awk4j.translator.Awk2JavaFX -- -hostscript1 sample.awk >sample.fx

  2. JavaFXスクリプトを JavaFX クラスにコンパイル
    ${JAVAFXC} [options] sample.fx

  3. JavaFX クラスを実行
    ${JAVAFX} [java-options] sample

Awk2JavaFX コマンド (トランスレータ)

${Awk2JavaFX} [ options ] AWKスクリプト.awk (クラス名として使用するため英大文字で始まる英 数字を推奨)
 or
${Awk2JavaFX} [ options ] -srcname 生成するクラス名 --source 'AWKスクリプト'

主なオプション
    -hostscript 1         ホストスクリプト埋め込み指定の有効化 (0)
    -include include-dir  インクルードライブラリ ("../lib/include")
    -package package-name 出力パッケージ名 ("")
    -srcname sorce-name   クラス名 ("Script")

    -d output-dir         JavaFXスクリプト出力ディレクトリ ("")
 or
    > output-script-file  リダイレクトで出力

javafxc コマンド (コンパイル)

$(JAVAFX_HOME)/bin/javafxc [ options ] JavaFXスクリプト.fx

主なオプション
    -cp クラスパス
    -d output-dir         クラスファイル出力ディレクトリ

javafx コマンド (実行)

$(JAVAFX_HOME)/bin/javafx [ java-options ] JavaFXクラス名

実行時に、コマンドラインパラメータを指定する場合は、 以下の方法にて指定する。

Note: $(SUBSEP): 多次元配列の添字区切り文字で"\034” (使用例は makefx 参照)
JavaFX でコマンドパラメータを設定する標準的な方法がないため暫定対応。

インストールおよび環境設定

JavaFX の導入

  1. Java SDK
  2. JavaFX SDK
« ディレクトリ構成 »
 awk4j        # awk4j を展開したディレクトリ
 +-- lib
 +-- ext
 +-- sample   # サンプルディレクトリ
   +-- resources
   +-- bin
   +-- src    # サンプルソース
   makefx     # JavaFX を実行するための makeファイル

  サンプルを実行する
$ make -f makefx sample

Note: 詳細は、makeファイルおよびサンプルソースを参照。

JavaFX 関連リンク


JavaFX Linux Support
JavaFX サポート
JavaFX Support
  1. JavaFX サポートとは
  2. さあ始めよう
    1. サンプル 1 (簡易ブラウザ)
    2. サンプル 2 (月齢計算)
    3. サンプル 3 (素数を求める)
    4. サンプル 4 (RSS閲覧)
    5. サンプル 5 (マンデルブロ集合)
  3. コマンドリファレンス
    1. Awk2JavaFX コマンド (トランスレータ)
    2. javafxc コマンド (コンパイル)
    3. javafx コマンド (実行)
  4. JavaFX の導入
  5. JavaFX 関連リンク