連載
» 2007年06月13日 00時00分 UPDATE

小山博史のJavaを楽しむ(6):JavaFXでJava RIA開発はどれくらい変わるの? (2/3)

[小山博史,ガリレオ]

簡単な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の実行画面 図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で作ったサンプルの実行画面 図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ライブラリを意識して作ったサンプルの実行画面 図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 RhinoJava 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:

編集部注:Mozilla Rhinoについての詳細を知りたい読者は、連載第1回の「JavaとJavaScriptの親しい関係」をご参照願います。

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に従った方法で行えます。

Copyright© 2014 ITmedia, Inc. All Rights Reserved.

TechTargetジャパン

ホワイトペーパー(TechTargetジャパン)

注目のテーマ

Focus

- PR -

転職/派遣情報を探す

【転職サーチ】SIer/Web企業/新規事業 スマホ開発で、あなたのキャリアを生かす

「派遣・フリーで働くメリット」とは? 活躍する派遣エンジニアの本音

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。