BT

最新技術を追い求めるデベロッパのための情報コミュニティ

寄稿

Topics

地域を選ぶ

InfoQ ホームページ アーティクル JavaFX 2.0 - Javaによるリッチクライアント基盤 (前編)

JavaFX 2.0 - Javaによるリッチクライアント基盤 (前編)

リッチクライアントを構築するためのJavaFXは、2010年のJavaOneカンファレンスにおいてJavaのライブラリとして生まれ変わることが発表されました。そして西海岸時間の526日、新しいバージョンであるJavaFX2.0のパブリックベータが公開され、だれもが新しいJavaFXを試すことができるようになりました。

そこで、2回に渡ってJavaFX 2.0を紹介していきます。

もともとJavaFXは、Adobe Flash PlatformやMicrosoft Silverlightなどに対抗すべく、Sun Microsystem (現Oracle)がリリースしたRIAのためのプラットフォームでした。JavaFXはJavaとは異なるパッケージとして提供され、JavaFX Scriptというスクリプト言語によって記述を行なってきました。

それが、なぜJavaのライブラリとして生まれ変わったのでしょう。それを理解するために、JavaFXの成り立ちについて振り返ってみましょう。

JavaFX 2.0に至る道

JavaFXのオリジナルは、2000年代前半に当時SeeBeyondに所属していたChristopher Oliver氏(図1)によって個人的に開発されてきたForm Follows Function (F3)です。

Christopher Oliver氏
図1 Christopher Oliver氏

F3はSwingの部品と、円や四角などのJava 2Dのグラフィック要素を同列に扱うことができるスクリプト言語でした。F3には以下のような特徴的な文法を有していました。

  • 宣言的文法
  • バインド
  • 関数型

宣言的文法はJavaScriptのオブジェクトリテラルのようにオブジェクトを生成するための文法です。宣言的文法を使用することで、UIのツリー構造を簡潔に表すことができます。

バインドは2つの変数を同期させるための機構です。バインドされた変数は一方が値を更新すると、他方が自動的に更新され、常に同じ値を示すようになります。特にUIではMVC構造におけるModelとViewにバインドを使用することで、オブザーバーパターンなどを使用せずとも同期を行なうことが可能でした。

関数型は多くのスクリプト言語でも提供している機能で、関数を第一級オブジェクトとして扱うことができます。関数型を使用してクロージャを記述することも可能でした。

その後、2005年9月にSeeBeyondはSun Microsystemsに買収され、F3はSun Microsystemsにおいて開発されることになりました。そして、2007年のJavaOneでF3はJavaFXと名前が変更され、大々的に発表されたのです。

JavaFXは、JavaFX Script言語を使用して記述を行ないます。JavaFX ScriptでもF3の特徴的な文法はそのまま引き継がれています。

また、もともとF3はデスクトップでの動作を想定していましたが、JavaFXに変更されてから携帯電話やセットトップボックスなどの組み込み用途にまでターゲットが広げられました。

JavaFX 1.0がリリースされたのが、2008年12月です。その後、JavaFX 1.3までバージョンアップが行なわれ、携帯電話向けのJavaFX Mobileとテレビ向けのJavaFX TVもリリースされています。

しかし、大々的に発表されたにもかかわらず、JavaFXの普及はかなりスローペースでした。特に携帯電話はAndroidが主流になってしまい、JavaFX Mobileを採用するキャリアはありませんでした。

そのような状況でSun MicrosystemsがOracleに買収されたのです。買収が完了した2010年1月に、OracleがJavaFXに投資を続けると発表されています。しかし、JavaFXのロードマップは明示されませんでした。

そして、前述したように2010年10月に開催されたJavaOneでJavaFXをJavaのライブラリとすることが発表されたのです。また、この決定に合せて、JavaFX 2.0をデスクトップ向けに限定し、普及の見込みのないJavaFX MobileおよびJavaFX TVの開発は中止されることになりました。

JavaFXを率いているRichard Bair氏がFX Experienceにこの決定の理由について寄稿しています。

 


The only language that could be used to build JavaFX applications was JavaFX Script. I always felt this was a needless restriction. In addition, I felt that it was actually a bad thing for JavaFX Script the language for a couple of reasons. First, since all our APIs were in JavaFX Script, it meant that JavaFX Script had to be changed to be a good language for writing APIs, whereas it was originally designed to be a good language for scripting UIs. Sometimes this created a design tension.

JavaFXアプリケーションを作成するために使用できる唯一の言語はJavaFX Scriptだけでした。私は常にこのことが必要のない制約であると感じていました。加えて、これが実際には後述する複数の理由によりJavaFX Scriptにとっても悪いことではないかと感じていました。第一に、すべてのAPIがJavaFX Scriptで記述されるため、JavaFX ScriptがAPIを書くために適した言語に変わらざるをえないということです。しかし、JavaFX ScriptはもともとUIを記述するための言語としてデザインされていました。時に、これがデザインの葛藤を生みだしていたのです。

FX Experience - JavaFX 2.0より引用


 Richard Bair氏
図2 Richard Bair氏

つまり、JavaFX ScriptはAPIを書くための言語と、UIを記述するための言語という2つの側面があり、その両面にフォーカスしてリソースを注入することが難しかったということです。たとえば、JavaFX Scriptのコンパイラ開発にはBrian Goetz氏が一時期参加していました。しかし、Goetz氏はJava SEの開発においても中心的な人物です。Goetz氏がJavaFX Scriptの開発に携わってしまうと、Java SEの開発が滞ってしまうのでした。

JavaFX Scriptが言語として成熟するには時間がかかります。しかし、そこまでの時間はありません。そこで、OracleはAPIを記述することを重視し、実績のあるJavaを採用したのです。

しかし、このことによりUIの記述性が落ちてしまうことは明らかです。特に宣言的文法が使えなくなってしまったことにより、UIの構造を容易に記述できなくなってしまいました。

もう1つの問題が開発ツールではないかと筆者は考えています。JavaFX ScriptはOracleのIDEであるNetBeansでサポートされていました。しかし、Adobe Flash Builder、Flash ProfessionalやMicrosoft Blendに相当するグラフィカルに開発を行なう開発ツールは最後までリリースされませんでした。

RIAを構築するに当たってデザイナーの果たす役割は非常に重要です。しかし、デザイナーが使えるツールが提供されてこなかったわけです。Adobe PhotoshopとIllustratorからJavaFXへインポートを行なうことは可能ですが、ワークフローはそこで切れてしまいます。

これはJavaFX 2.0においても同じです。JavaFX 2.0はJava開発者がターゲットになっており、デザイナーを取り込む方策がはっきりしていません。しかし、JavaFX 2.0が普及するかどうかはデザイナーの取り込みにかかっていると、筆者は考えています。

なお、JavaFX 2.0においてサポートされなくなったJavaFX Scriptですが、オープンソースプロジェクトのProject Visaageで開発が続けられることになりました。Pro JavaFX Platformなどの書籍の著者でもあるStephen Chin氏が中心になって開発を行なっており、F3の作者であったChristopher Oliver氏もコミッターとして参加しています。

現在もJavaFX 2.0に対応させるべく、活発に活動が行なわれています。

JavaFX 2.0でHello, World!

JavaFX 2.0のプログラムの構造を知るために、おなじみのHello, World!をJavaFX 2.0で記述してみることにしましょう。

JavaFX 2.0のSDKはJavaFXのダウンロードページよりダウンロードすることができます。現状、Windows版だけが利用可能です。ここではJDK 6u25を使用して、JavaFXを動作させています。

ダウンロードしたJavaFX SDKを展開すると、rtディレクトリが作成され、そこにbinディレクトリとlibディレクトリが作成されます。libディレクトに配置されているjfxrt.jarファイルをクラスパスに追加することで、JavaFXのプログラムのコンパイル、実行を行なうことができます。

Hello, World!を表示するHello.javaを以下に示します。

import javafx.application.Application;
import javafx.scene.Group; import javafx.scene.Scene; import javafx.scene.control.Label; import javafx.stage.Stage; public class Hello extends Application { @Override public void start(Stage stage) { // コンテナ Group container = new Group(); // シーングラフのルート要素を生成し、コンテナを貼る Scene scene = new Scene(container, 100, 20); stage.setScene(scene); // ラベルを生成しコンテナに貼る Label label = new Label("Hello, World!"); container.getChildren().add(label); // 表示 stage.setVisible(true); }     public static void main(String[] args) {
        Application.launch(Hello.class, null);
    } }

JavaFX 2.0のアプリケーションはApplicationクラスのサブクラスとして作成します。アプリケーションの起動時に、Applicationクラスのstartメソッドがコールされるので、UIの記述はここで行ないます。

JavaFX 2.0において、SwingのJFrameクラスに相当するのがStageクラスです。そこに、Swingのルートペインに相当するSceneオブジェクトを貼り、更にSceneオブジェクトにコンテナとなるオブジェクトを貼ります。ここではコンテナとしてGroupクラスを使用しました。

コンテナにはUIの部品(JavaFXではコントロールと呼びます)を貼っていきます。ここではLabelクラスを使用して文字列を表示しています。

アプリケーションの起動にはApplicationクラスのlaunchメソッドを使用します。

Swingの場合、明示的にSwingのスレッドで実行させるためのコードを記述する必要がありました。しかし、JavaFXではApplicationクラスが行なうため、明示的に記述する必要はありません。

このApplicationクラスの構成はアプレットに似ています。実際、JavaFXアプリケーションをアプレットやJava Web Startとして実行させることも可能です。しかし、アプレットとして実行する場合でも、ソースの変更は必要ありません。

では、ソースをコンパイルして、実行してみます。ここでは、SDKのrtディレクトリと同じ場所にHello.javaを配置しました。

C:\javafx>javac -cp rt\lib\jfxrt.jar;. Hello.java

 

C:\javafx>java -cp rt\lib\jfxrt.jar;. Hello

実行結果を図3に示します。

 Helloクラスの実行結果
図3 Helloクラスの実行結果

ここで示したように、JavaFXアプリケーションは、ベースとなるクラスは異なりますが、UIの構築はSwingに同様に行なうことができます。すでにSwingを使用したことがあるユーザであれば、すぐにでもJavaFXを使うことができるようになるはずです。

 

JavaFX 2.0の機能

前節でJavaFXの構成を紹介しました。本節では、JavaFX 2.0の機能を見ていくことにします。以下にJavaFX 2.0の主な機能を列挙しました。

  • Prismグラフィックエンジン
  • シーングラフ
  • UIコントロール
  • メディア
  • CSS
  • バインド
  • アニメーション
  • エフェクト
  • 非同期処理
  • Swingとの連携

前編ではUIコントロールまでの機能、後編でそれ以降の機能について説明していきます。

Prismグラフィックエンジン

リッチクライアントにおいて最も重要なのは、描画性能です。近年のクライアントでは2Dだけでなく3Dも使用され、アニメーションやエフェクトなども多く使われます。そのためには、高い描画性能が必須です。

JavaFX 2.0ではGPUによるグラフィックアクセラレーションを最大限活用するPrismグラフィックエンジンが新たに採用されています。

PrismがサポートしているGPUを表1にまとめました。表1に示した以外のGPUでは描画に従来のJava 2Dのパイプラインが使用されます。

 

表1 Prismがサポートするグラフィックカード

メーカー GPU
AMD Mobility Radeon HD 3400シリーズ
  Mobility Radeon HD 4000シリーズ
  Mobility Radeon HD 5000シリーズ
  Radeon HD 2400シリーズ
  Radeon HD 4000シリーズ
  Radeon HD 5000シリーズ
  Radeon HD 6000シリーズ
Intel GMA X4500シリーズ
  GMA X4500HDシリーズ
  GMA 3150シリーズ
  GMA X3100シリーズ
  GMA X3500シリーズ
NVIDIA GeForce 8Mシリーズ
  GeForce 8シリーズ
  NVS 3100M
  GeForce 200Mシリーズ
  GeForce 200シリーズ
  Quadro FX 260M
  Quadro FX 370

 

従来のSwingのグラフィックエンジンはイベント処理と描画処理を単一のスレッドで処理してきました。しかし、イベント処理のために描画が遅延されるなどの欠点があります。そこで、Prismグラフィックエンジンは、可能であればイベント処理と描画処理を別々のスレッドで行ないます。

Prismグラフィックエンジンを採用することで、JavaFX 2.0はJavaFX 1.3に比べて大幅に描画性能を向上させることが可能になりました。

シーングラフ

一般的に、UIの構造はツリーで表すことができます。

たとえば、Swingではフレームにパネルを貼り、パネルにボタンやテキストフィールドなどを貼っていくことで、UIを構成していきます。しかし、Swingではボタンなどの部品と、四角や丸などのグラフィック要素を同列に扱うことはできません。

JavaFXでは、部品やグラフィック要素など描画の対象となる要素はすべてjavafx.scene.Nodeクラスのサブクラスとして実装されています。このため、UIの構造を表すツリーにおいても、部品やグラフィック要素を区別することなく扱うことができます。そして、このUIの構造を表すツリーをシーングラフと呼びます。

JavaFX Scriptの宣言的文法は、このシーングラフを表すために使用されてきました。残念ながらJavaFX 2.0では宣言的文法はサポートされていないため、シーングラフを手続き的に表す必要があります。

たとえば、図4で表されるUIのシーングラフをJavaFXで表してみることにします。以下に、シーングラフの構成部分を示しました。

  

図4 シーングラフの例

 

        Group root = new Group();
 
        Scene scene = new Scene(root);
        stage.setScene(scene);
 
        // 円
        Circle circle = new Circle(200.0, 200.0, 300.0, Color.PINK);
        root.getChildren().add(circle);
 
        // ボーダーレイアウト
        BorderPane borderPane = new BorderPane();
        root.getChildren().add(borderPane);
 
        // ブラウザ
        WebEngine engine = new WebEngine();
        WebView view = new WebView(engine);
        borderPane.setCenter(view);
 
        // 水平ボックス
        HBox hbox = new HBox(10);
        borderPane.setTop(hbox);
 
        // ラベル
        Label label = new Label("URL:");
        hbox.getChildren().add(label);
 
        // テキスト入力
        TextBox textBox = new TextBox(40);
        hbox.getChildren().add(textBox);
 
        // ボタン
        Button button = new Button("Open");
        hbox.getChildren().add(button);

シーングラフは、コンテナのaddメソッドやセッターメソッドをコールして描画要素を貼っていくことにより構築します。この例ではグラフィック要素である円もUI部品と同じようにコンテナに貼っています。

図5に実行結果を示しました。円は背景として描画されていることが分かります。

 

実行結果

図5 実行結果

 

UIコントロール

JavaFXはUIコントロールと呼ばれる独自のUI部品群を提供しています。UIコントロールにはボタンやラベル、チェックボックスなどが含まれます。図6にUIコントロールの代表的な部品を示しました。

ボタンなどのUIを構築するための標準的な部品以外に、チャート(グラフ)なども提供されています。

 

UIコントロールの代表的な部品

図6 UIコントロールの代表的な部品

 

UIコントロールはJavaFX 1.2から提供されており、プロパティなどはそのまま引き継がれています。このため、JavaFX ScriptでUIコントロールを使用した経験のあるデベロッパーであれば、すぐにでも使えるようになるはずです。

詳しくは後編で解説しますが、UIコントロールはCSSを使用することで、ビューを変更することも可能です。

また、UIコントロールではHTMLドキュメントを表示するブラウザも提供しています。このブラウザはWebKitがベースとなっています。つまり、GoogleのChromeやAppleのSafariと同列のブラウザを、JavaFXでも使用できるのです。

JavaFXのブラウザでは以下の処理が可能です。

  • JavaScript、CSSを含むHTMLドキュメントの描画
  • HTMLドキュメントのリロード
  • HTMLドキュメントのDOMの操作
  • JavaScriptコマンドの実行
  • イベント処理

ブラウザはHTMLドキュメントを解釈するjavafx.scene.web.WebEngineクラスと、描画を行なうjavafx.scene.web.WebViewクラスから構成されます。たとえば、http://javafx.com/を表示するのであれば、以下のように記述します。

        WebEngine engine = new WebEngine("http://javafx.com/");
        WebView view = new WebView(engine);

WebEngineクラス、WebViewクラスを使用すれば、アプリケーションに容易にカスタマイズしたブラウザを埋めこむことができます。ブラウザをカスタマイズした例を図7に示します。

 

カスタマイズしたブラウザの例

図7 カスタマイズしたブラウザの例

 

後編では残りの機能について解説する予定です。なお、本記事で使用したサンプルはすべてGitHubInfoQJavaFXDemoリポジトリよりダウンロードすることができます。

この記事に星をつける

おすすめ度
スタイル

BT