JavaFXでJava RIA開発はどれくらい変わるの?
Sunは攜帯端末向けのGUIアプリケーションもターゲットとしているようで、JavaFX Mobileというシステムも提供していくとアナウンスしています。こちらは、従來よりもパワーがある攜帯端末で、Java SEが動作するようなものを想定しているようです。
PCのデスクトップだけでなく、この先進的な攜帯端末でも動くGUIアプリケーションを簡単に作成できるということが、JavaFX Scriptの売りとなっているようです。昨年から続いているEoDの流れにも沿っているのでしょう。ということで、早速JavaFX Scriptを使ってみました。
図1 JavaFX Script Studiomoto Demoの畫面
■ JavaFX Scriptの使いどころとは?
JavaFX Scriptは、SunのJavaFXのサイトで紹介されています。RIA(Rich Internet Application)を簡単に実裝できることが売りですが、Javaプログラマにとっては、既存のスクリプト言語との関係が気になるところです。Swingライブラリを使ったプログラミングの方が、Javaの文法で行える分、気が楽だというのが正直なところなので、こういったスクリプト言語の存在に価値を見いだすとしたらどこか、というのが最初に気になります。
■ Webブラウザの出現でUIデザインの仕方は変わった
一昔前のコンピュータ用アプリケーションの開発においては、ユーザーインターフェイスデザインというのは、開発者が片手間にやっていたり、コンピュータのユーザーインターフェイスに詳しいエンドユーザーが指示をしていたり、というのが普通の世界でした。
しかし、Webブラウザの出現によって、狀況は変わってきています。いまや、Webサービスの開発においては、デザインチームが畫面デザインをし、Web開発チームがそれをXHTML+CSSやAjaxで実裝し、サーバサイドは開発チームがプログラミングをするといった體制で開発が増えてきています。賛否両論はあるようですが、GUIアプリケーションのモデルとして有名なMVCモデルをWebアプリケーション開発に適用していることが多いはずですし、多くのフレームワークは、基本的にこのモデルを採用しています。
■ RIA開発ではより柔軟なGUIコンポーネントが必要
このように、RIAの開発が要求されるようになってきていますが、これまでのようにWebブラウザに依存した技術だけでそれを実現するのは難しくなってき ています。これからは、より柔軟に、より高度なGUIコンポーネントを組み合わせることができて、しかもインターネットに対応したアプリケーションを開発 できる技術が必要なのです。
■ JavaFX Scriptはデザイン側やクライアント開発側で使われる?
こうして見ると、JavaFX Scriptを使うのは、実はサーバサイドで開発をしているJavaプログラマよりは、現在、XHTML+CSSやAjax回りを使っているWeb開発 チームが一番関係してきそうです。このチームのメンバが、Webアプリケーション開発時にJavaScriptやFlashを使っていたのと同じように、デスクトップでも攜帯端末でも同じように動作するRIAを開発するに當たって、JavaFX Scriptを使うことになると考えられます。
ですから、JavaFX Scriptを評価するに當たっては、こういった開発體制で利用できそうなのか、JavaScriptやFlashを使うのと同じくらい簡単に使えるの か、といった項目が重要ではないでしょうか。こんなことを考えながら、いくつかの簡単なサンプルコードを作ってみました。
■ ダウンロードして、デモを試す
JavaFX Scriptのオープンソース実裝であるOpenJFXのサイトで は、活発に開発がされていて、バージョンアップが頻繁に行われています。アーカイブはzip形式とtar.gz形式が用意されていますので、好きな方をダ ウンロードしてください。ここでは、記事執筆時にダウンロードしたOpenJFX-200705302107.zipを使って動作確認をしていますので、 あらかじめご了承ください。
OpenJFXのサイトでは、ライセンスは將來的にはGPLとなると書いてありますが、記事執筆時にダウンロードしたものには、「Technology Evaluation License」が同梱されていました。
■ Java Web Startを使ったデモ
ところで、このサイトには「Demos」と記載してあるところに、JNLPを使ったJava Web Startで起動するデモも用意されています。ちょっと様子を見てみたいというだけでしたら、このデモをダウンロードして動作させてみるといいでしょう。こういうのを使うと、Java Web Startの良さを実感できるはずです。
図2 JavaFX Script Tesla Demoの畫面
■ デスクトップ上でも、デモを動かす
ともあれ、手元でも動作をさせてみましょう。ファイルをダウンロードしたら展開します。ここでは、Windows XPを使って確認をしました。展開した結果できたディレクトリは、C:\OpenJFXという名前に置き換えています。なお、後で作成するサンプルコード 用にC:\OpenJFX\sampleも作成しておきました。
ダウンロードしたファイルに同梱されたjavafxpad.batは簡単なJavaFX Scriptプログラムの開発に使える便利なツールです。前述のJava Web Startのデモにもあります。早速使ってみました。
図3 JavaFxPadの実行例
■ 簡単なJavaFXアプリを作ってみよう!
さて、ここからはWindows Vistaを使って、実際に簡単なサンプルを作ってみます。ダウンロードしたファイルのbinディレクトリには、javafx.batなどの起動スクリプトがあります。文字コードがWindows-31Jのファイルしか使えなくなってしまうので、筆者は次のようなバッチファイルjfx.batを用意して、こちらを使うようにしました。見てのとおり、libディレクトリにあるjavafxrt.jar、Filters.jar、swing-layout.jarを使います。
また、スクリプトの起動には、net.java.javafx.FXShellクラスを使います。ここでは、ファイルのエンコードをUTF-8としています。プログラムを作成するときには、UTF-8で保存するように気を付けてください。なお、javaコマンドへのパスはあらかじめ通しておきます。
| jfx.bat |
| @echo off set CP=.;../lib/javafxrt.jar set CP=%CP%;../lib/Filters.jar set CP=%CP%;../lib/swing-layout.jar java -Dfile.encoding="UTF-8" -cp %CP% net.java.javafx.FXShell %1 %2 %3 %4 %5 %6 %7 %8 %9 |
| SimpleSwingSample.java |
| import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.SwingUtilities; public class SimpleSwingSample { ????public static void main(String[] args) { ????????SwingUtilities.invokeLater(new Runnable() { ????????????public void run() { ????????????????createAndShowGUI(); ????????????} ????????}); ????} ??? private static void createAndShowGUI() { ????????JFrame f = new JFrame(); ????????f.setTitle("タイトル:SimpleSwingSample"); ????????f.setSize(300, 80); ????????JButton button = new JButton("OK"); ????????f.getContentPane().add(button); ????????button.addActionListener(new ActionListener() { ????????????public void actionPerformed(ActionEvent event) { ????????????????System.out.println("OK"); ????????????} ????????}); ????????f.setLocation(200, 100); ????????f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); ????????f.setVisible(true); ????} } |
コンパイルをして実行してみます。javacコマンドへのパスは通しておいてください。ソースファイルの文字コードを指定する必要があるので、「-encoding」オプションを付けている點にも注意してください。
| コンパイルしてjavaコマンドを実行 |
| >javac -encoding UTF-8 SimpleSwingSample.java >java SimpleSwingSample |
図4 SimpleSwingSample.javaの実行畫面
■ JavaFX Scriptで記述すると?
これを、JavaFX Scriptで記述すると、次のようになります。文法事項については、JavaFX Scriptの言語仕様がまだドラフトであることと、実裝も頻繁に更新されていることから、あまりくどくどと説明せずに、重要な點だけを解説することにします。
一目見て分かることは、非常に簡単に記述できるということでしょう。畫面を表すのがFrameで、その屬性をCSSと同じような感じに指定できるようになっています。Swing版のプログラムと比較してもJavaFX Scriptの方が斷然書きやすそうです。また、SwingUtilitiesも、この程度のプログラムなら必要ないようです。
| JavaFX Scriptで記述 |
| import javafx.ui.*; import java.lang.System; Frame { ????title: "タイトル:SimpleFxSample" ????screenx: 200 ????screeny: 100 ????width: 300 ????height: 80 ????content: Button { ????????text: "OK" ????????action: operation() { ????????????System.out.println("OK"); ????????} ????} ????visible:true } |
Swingプログラミングでは、Buttonには、addActionListenerメソッドを使って、ActionListenerを登録していましたが、JavaFX Scriptでは、actionという屬性にoperation()を指定し、そこでボタンを押されたときの処理を記述します。
ここでは、java.lang.Systemクラスを使って、「OK」という文字列をコンソール畫面へ出力していますが、このクラスをimportしていることに注意してください。また、FrameやButtonといったクラスはjavafx.uiパッケージのクラスで、「import javafx.ui.*;」を宣言していないと、エラーとなります。
実行をするには、次のようにします。先ほど作成したバッチファイルを使っています。コンパイルスレッドがイベントディスパッチスレッド上で動作していることがコンソール畫面へ表示され、その後に畫面が表示されます。
| JavaFXアプリケーションを実行 |
| >jfx.bat SimpleFxSample.fx compile thread: Thread[AWT-EventQueue-0,6,main] compile 2.216 init: 1.466 |
図5 JavaFX Scriptで作ったサンプルの実行畫面
■ JavaのSwingライブラリを意識したコーディングをすると?
JavaのSwingライブラリを意識したコーディングもできます。こちらでも隨分コンパクトに書けます。JavaFX Scriptの書き方に慣れないJavaプログラマはこちらの書き方の方が書きやすいかもしれません。javax.swing.JFrameなど、必要なクラスをimportしているので、忘れないようにしてください。
| JavaのSwingライブラリを意識したコーディングの例 |
| import javax.swing.JFrame; import javax.swing.JButton; import java.awt.event.ActionListener; import java.lang.System; var f = new JFrame(); f.setTitle("タイトル:CallDirectSwing"); f.setSize(300, 80); var button = new JButton("OK"); f.getContentPane().add(button); button.addActionListener(new ActionListener() { ????operation actionPerformed(event) { ????????System.out.println("OK"); ????} }); f.setLocation(200, 100); f.setDefaultCloseOperation(f.EXIT_ON_CLOSE); f.setVisible(true); |
図6 JavaのSwingライブラリを意識して作ったサンプルの実行畫面
■ スクリプトの起動方法を考える
Javaプログラムとの連攜を考えると、どうやってJavaプログラムからJavaFX Scriptプログラムを起動するのかについては確認をしておく必要があります。起動スクリプトから分かりますが、net.java.javafx.FXShellはmainメソッドを持っているので、次のようにmainメソッドを呼ぶのが一番簡単なようです。とはいえ、これはJavaのスクリプティング標準の方法ではありません。
| FxRunner.java |
| import net.java.javafx.FXShell; public class FxRunner { ????public static void main(String[] args) { ????????if (args.length == 0) { ????????????args = new String[] {"SimpleFxSample.fx"}; ????????} ????????try { ????????????FXShell.main(args); ????????} catch (Exception e) { ????????????e.printStackTrace(); ????????} ????} } |
コンパイル時、実行時にはjavafxrt.jarや、swing-layout.jarファイルにクラスパスを通すことを忘れないようにしましょう。必要であれば、Filters.jarにもクラスパスを通します。
| FxRunner.javaの実行結果 |
| >javac -classpath ..\lib\javafxrt.jar -encoding UTF-8 FxRunner.java >java -cp ..\lib\javafxrt.jar;..\lib\swing-layout.jar;. FxRunner compile thread: Thread[AWT-EventQueue-0,6,main] compile 1.903 init: 1.123 |
■ JSR-223に従うスクリプティングエンジン
Javaスクリプティングを使って、JavaFX Scriptのエンジンを利用する前に、JSR-223に従うスクリプティングエンジンの実裝がどれくらい進んでいるのかをチェックしてみましょう。次のプログラムはクラスパスに登録されているスクリプトエンジンについて、簡単な情報と、実裝しているインターフェイスの一覧とを表示するプログラムです。javax.scriptパッケージに含まれるScriptEngineManagerクラスやScriptEngineFactoryクラスの簡単な使用例にもなっています。
| CheckEngine.java |
| import java.util.List; import javax.script.ScriptEngine; import javax.script.ScriptEngineFactory; import javax.script.ScriptEngineManager; public class CheckEngine { ????public static void main(String[] args) { ????????ScriptEngineManager engineManager ????????????= new ScriptEngineManager(); ????????List<ScriptEngineFactory> factories = engineManager ????????????.getEngineFactories(); ????????for (ScriptEngineFactory factory : factories) { ????????????System.out.println(factory.getLanguageName() + "," ????????????????+ factory.getLanguageVersion() + "," ????????????????+ factory.getEngineName() + "," ????????????????+ factory.getEngineVersion()); ????????????ScriptEngine engine = engineManager.getEngineByName( ????????????????factory.getLanguageName()); ????????????if (engine != null) { ????????????????Class clazz = engine.getClass(); ????????????????System.out.println("Engine Class:"+ clazz.getName()); ????????????????System.out.println("Interfaces:"); ????????????????for (Class i : clazz.getInterfaces()) { ????????????????????System.out.println(" "+i); ????????????????} ????????????} ????????} ????} } |
これを実行すると、筆者の環境では次のように表示されました。JavaFX Script Engineに関する情報が表示されているのが分かります。なお、Mozilla RhinoはJava SE 6に同梱されているECMAScript Engineです。これを見ると、Mozilla Rhinoは「javax.script.Invocable」や「javax.script.Compilable」といったインターフェイスを実裝していますが、OpenJFXではこれらの実裝はまだされていないということが分かります。
| CheckEngine.javaの実行結果 |
| >java -cp ..\lib\javafxrt.jar;..\lib\swing-layout.jar;. CheckEngine ECMAScript,1.6,Mozilla Rhino,1.6 release 2 Engine Class: com.sun.script.javascript.RhinoScriptEngine Interfaces: interface javax.script.Invocable interface javax.script.Compilable FX,0.1,JavaFXEngine,0.1a Engine Class: net.java.javafx.jsr223.JavaFXScriptEngine Interfaces: |
■ JavaFX Scriptを実行するプログラム
それでは、スクリプトを起動するプログラムを書いてみましょう。ここでは、引數については考えないで、単純に起動する方法だけ実現してみました。java.io.FileReaderクラスを使っていることから、ファイルのクローズを確実にする必要があるために、記述は長くなっていますが、ポイントはrunScriptメソッド內の処理になります。
ここで先ほどのプログラムで得たJavaFX Scriptingのエンジン名「FX」を使って、「manager.getEngineByName("FX")」のようにScriptEngineの インスタンスを取得しています。後は、これを使って「engine.eval(reader);」としているだけです。
| ScriptRunner.java(抜粋)(全ソースはこちら) |
| (略) import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import javax.script.ScriptException; import javax.swing.SwingUtilities; public class ScriptRunner { ????class ExecuteScript implements Runnable { (略) ????????private void runScript(Reader reader) { ????????????ScriptEngineManager manager ????????????????= new ScriptEngineManager(); ????????????ScriptEngine engine = manager.getEngineByName("FX"); ????????????if (engine != null) { ????????????????try { ????????????????????engine.eval(reader); ????????????????} catch (ScriptException e) { ????????????????????e.printStackTrace(); ????????????????} (略) ????public static void main(String[] args) { (略) ????????ScriptRunner runner = new ScriptRunner(); ????????SwingUtilities.invokeLater( ????????????runner.new ExecuteScript(fileName)); ????} } |
もう一點、注意する必要があります。最後の行でSwingUtilitiesクラスのinvokeLaterメソッドを使ってスクリプト実行のメソッドを 呼び出しています。畫面を表示するプログラムはイベントディスパッチスレッドから呼び出す必要があるために、このようにしています。
これを実行すると、JavaFX Scriptのファイルを読み込んで実行できるようになります。変數のバインドなどもJSR-223に従った方法で行えます。
■ アニメーションプログラムを作ってみよう
JavaFX Scriptでは、アニメーションプログラムを簡単に作成できるということなので、それについても確認してみました。単純なデジタル時計を作成したのですが、次のようになります。
ここでは、javafx.ui.LabelクラスをextendsしたクラスとしてDigitalClockを用意しています。パッケージも使えるので、fxパッケージとして、ディレクトリfxにファイルを置いています。
■ JavaFX Scriptのtriggerキーワード
JavaFX Scriptではtriggerというキーワードが あり、ある処理が発生したときに一緒に行いたい処理を記述できます。ここでは、DigitalClockの屬性cについて代入がされるたびに、Dateク ラスのインスタンスを生成し、テキスト形式にフォーマットしてjavafx.ui.Labelクラスの屬性textへ代入しています。
また、コンストラクタが呼ばれたときに屬性runningをtrue とし、runningがtrueの間は屬性cの値を更新し続けるようにしています。ただし、「c = [1..100] dur 1000 continue if running;」という処理については、サンプルにあった処理なのですが、言語リファレンスのページであるopenjfx: The JavaFX Programming Languageには説明がないので、正確な意味は分かりません。
dur演算子については、デモに含まれるJavaFX Canvas Tutorialに記述があります。durationの 意味で、この場合は1000ミリ秒間に10ミリ秒ごとに1から100の値がcへ代入されます。殘りの「continue if running」の部分については、殘念ながらそこにも説明がありませんが、動作を見る限りはrunningがtrueの間、この処理を続けることになり ます。
| fx\DigitalClock.fx |
| package fx; import javafx.ui.*; import javafx.ui.canvas.*; import java.util.Date; public class DigitalClock extends Label { ????attribute running: Boolean; ????attribute c : Number; } trigger on DigitalClock.c = newValue { ????var dNow = new Date(); ????text = dNow format as <<yyyy-MM-dd HH:mm:ss zzz>>; } trigger on new DigitalClock { ????running = true; ????c = [1..100] dur 1000 continue if running; } |
■ デジタル時計の起動プログラム
これを使った畫面を表示するには、次のようなプログラムを用意します。ほかのクラスと同じように、fx.DigitalClockクラスをインポートして 使っています。このクラスはjavafx.ui.Labelと同じように使えますが、インスタンスを生成すると、同時に動作し始めるので、畫面を終了する ときには、停止する必要があります。それが「onClose: operation() { dc.running = false; }」の部分になります。
| DigitalClockFrame.fx |
| import javafx.ui.*; import javafx.ui.canvas.*; import java.util.Date; import fx.DigitalClock; var dc = new DigitalClock(); Frame { ????title: "DigitalClock" ????width: 210 ????height: 240 ????centerOnScreen: true ????content: dc ????onClose: operation() { ????????dc.running = false; ????} ????visible: true }; |
図7 JavaFX Scriptによるデジタル時計の実行畫面
実行すると、デジタル時計の畫面が表示されて時間を刻むのが分かるはずです。アニメーションをさせたい場合は、DigitalClock.fxの 「trigger on DigitalClock.c = newValue { /* 処理 */ }」にアニメーション用の処理を記述すればいいだけなので、それほど難しくはないはずです。Swingプログラムでは結構意識が必要だったイベントディス パッチスレッドも、それほど意識しなくてもいいようです。
■ デモのアニメーション
同梱されているデモでも、オブジェクトが回転するなどのアニメーションが試せます。
図8 JavaFX Canvas TutorialデモのAnimation(実行環境はWindows XP)
■ RSSフィード表示アプリを作ってみよう
最後に、インターネットアプリケーションのサンプルも作成してみました。RSSフィードを読み込んでツリー形式で表示する単純なものです。JavaFX Scriptだけでは難しいので、RomeというAtom/RSS用のライブラリを使っています。RomeはJDOMを使うので、こちらも必要です。今回は、rome-0.9.jar、rome-fetcher-0.9.jar、jdom.jarを使って実裝しています。
ここでは、RssTreeというクラスを用意して、タイトルを保存する配列としてtitlesを用意し、タイトルと対になるURIを保存するマップをuriMapで用意しています。コンストラクタでフィードを読み込んで、RssTreeの初期化をしています。
■ JavaFX Scriptの面白い命令
特長的なのは、while文の中でエントリからタイトルと、それに対応するURIをRssTreeへ保持する処理をしているのですが、配列のtitlesへ「insert title into titles;」という命令で値を追加している點です。配列へは添え字を使って代入するのが普通なのですが、JavaFX Scriptには、こういった面白い命令が用意されているのです。
| RssTree.fx(抜粋)(全ソースはこちら) |
| (略) public class RssTree { ????attribute rss: String; ????attribute titles: String*; ????attribute uriMap: Map; } trigger on new RssTree { ????rss = "http://www.atmarkit.co.jp/rss/rss2dc.xml"; (略) ??? var entries = feed.getEntries(); ????uriMap = new HashMap(); ????var i = 0; ????while (i < entries.size()) { ???? (略) ????insert title into titles; ????i += 1; ????} } var rssTree = new RssTree(); Frame { ????height: 480 ????width: 600 ????content: Tree { ????????root: TreeCell { ????????????text: bind rssTree.rss ????????????cells: foreach (t in rssTree.titles) ????????????TreeCell { ????????????????text: t ????????????????cells: [ ????????????????????TreeCell { ????????????????????????text: rssTree.uriMap.get(t).toString() ????????????????????} ????????????????] ????????????} ????????} // TreeCell ????} // Tree ????visible: true } |
■ JavaFX Scriptのforeach文
rootのTreeCellへTreeCellを追加するに當たり、foreach文を使って登録しているあたりにも注目してください。こういった処理は癖があるので慣れるまで難しいと思いますが、同じ部品を繰り返し登録するのには便利です。
■ RSSフィード表示アプリの実行結果
実行時にはRomeとJDOMのJARファイルへもクラスパスを通すように気を付けてください。起動に成功すると、@ITのフィードを読み込んで表示します。エラー処理については記述していませんが、このようなプログラムも組めることが分かりました。
図9 JavaFX ScriptによるRSSフィード表示アプリの実行畫面
■ JavaFX Scriptを楽しむ
以上、ドキュメントが少ない中、インターネット上で公開されているサンプルと、ダウンロードしたアーカイブに同梱されているデモプログラムを中心にして簡 単なサンプルを作ってみましたが、本格的に使用するには、まだいろいろと苦労しそうですが、面白いプログラミング言語だと思いました。
最後にコンポーネントを組み合わせて表示するプログラム(ソースはこちら)も作成してみましたが、複雑なデザインの畫面も結構気軽に作成できそうです。
図10 ComponentTest.fxの実行畫面
■ RIAの元祖はJavaアプレットだった
思い起こせば、10年前にJavaアプレットという方法で、RIAを実現する言語としてJavaには注目していましたが、いろいろな経緯を経て、あまり使われなくなってしまいました。最近はJavaのプラグインが必要なサイトはほとんど見掛けません。
Swing も高性能なのですが、なかなかデスクトップサイドのアプリケーションで普及しているものはありません。筆者はかなりJava好きですが、Webブラウザ、 メールクライアント、オフィス製品など、どれもJavaアプリケーションのものは使っていません。しかし、Sunはあきらめていなかったのでしょう。ここ にきて、JavaFX Scriptでこの分野での巻き返しをしようとしているのではないでしょうか。まだまだ実力は未知數ですが、言語としては面白い機能を持っているので、楽 しめることは間違いありません。
■ Java SEと親和性のあるRIA
また、Javaには既存の膨大なライブラリがあり、JavaFX Scriptからは、それらを簡単に使えるという點は大きな魅力です。Java SEのアプリケーションやライブラリと親和性のあるスクリプト言語は、必ず開発に役立つはずです。
ただし、JavaFX Scriptは、高度なアニメーション機能を備えたGUIインターフェイスの開発を容易にすることに重點が置かれていますから、その點だけは忘れないようにした方がいいでしょう。以上の事柄を踏まえて、JavaFX Scriptを新しい開発に生かしていくといいのではないでしょうか。
總結
以上是生活随笔為你收集整理的JavaFXでJava RIA開発はどれくらい変わるの?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 为新购Thinkpad T410打造Wi
- 下一篇: 4个最新临时邮箱,全方位保护你的隐私