忍者ブログ

軽Lab

 Javaを中心とした、プログラミング関係のナレッジベース

Home > JavaFX入門 > FXMLを利用する(2)リソースバンドル/カスタムコンポーネント

FXMLを利用する(2)リソースバンドル/カスタムコンポーネント

前回に引き続き、FXMLの利用法について確認していく。今回は多言語対応のために使われるリソース・バンドル、そしてコンポーネントの部品化を可能にするカスタム・コンポーネントの利用法を見ていく。


■ リソース・バンドルの利用

 FXMLで多言語対応をしたい場合にはリソース・バンドル(ResourceBundleクラス)が利用できる。リソース・バンドルはJavaの標準クラスの1つで、地域別のメッセージをそれぞれファイル(*.properties)にまとめておくことで、実行環境のロケールに合わせたメッセージを出力する仕組みである。

 指定するロケールにより、使用するリソース・ファイルが変更される。使用されるファイル名は、以下の3つの中でより上に存在するファイル名が適用される。言語名・国名はLocaleクラスで指定する2文字のコードである(*1,*2)。よく使うロケールを表1に示す。

  1. (基底名)_(指定ロケールの言語名)_(指定ロケールの国名).properties
  2. (基底名)_(指定ロケールの言語名).properties
  3. (基底名.properties」

表1:基底名「TestFXML2」に対してロケールを指定した場合に使用されるリソース・ファイルの名称
ロケール ファイル名
指定なし TestFXML2.properties
Locale.JAPAN TestFXML2_jp_JP.properties
TestFXML2_jp.properties
Locale.US TestFXML2_en_US.properties
TestFXML2_en.properties

■ サンプルプログラム

 リソース・バンドルを利用するサンプルを以下に示す。サンプルではロケールに日本を選ぶことで、日本語のpropertiesファイルを使用している。

◇リソース
TestJavaFX(プロジェクト)
 ┗ src
   ┣ application
   ┃ ┣ TestFXML4.java
   ┃ ┗ TestFXML4.fxml
   ┣ TestFXML4_en.properties
   ┗ TestFXML4_ja.properties

◇サンプルコード
【TestFXML4.java】
package application;

import java.net.URL;
import java.util.Locale;
import java.util.ResourceBundle;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

/**
 * FXMLファイルを利用する4
 * 
 * @author karura
 *
 */
public class TestFXML4 extends Application
{
    public static void main(String[] args) {
        launch(args);
    }
    
    @Override
    public void start(Stage primaryStage) throws Exception
    {
        // フォント色がおかしくなることへの対処
        System.setProperty( "prism.lcdtext" , "false" );
        
        // FXMLファイルの読込
        URL             location    = getClass().getResource( "TestFXML4.fxml" );
        ResourceBundle  resources   = ResourceBundle.getBundle( "TestFXML4" , Locale.JAPAN );
        //ResourceBundle  resources   = ResourceBundle.getBundle( "TestFXML4" , Locale.US );
        FXMLLoader      fxmlLoader  = new FXMLLoader( location , resources );
        
        // シーングラフの作成
        fxmlLoader.setRoot( new VBox() );
        Pane    root        = (Pane) fxmlLoader.load();
        
        // シーンの作成
        Scene   scene       = new Scene( root , 200 , 40 );
        
        // ウィンドウ表示
        primaryStage.setScene( scene );
        primaryStage.show();
    
    }

}
【TestFXML4.fxml】
<?xml version="1.0" encoding="UTF-8"?>

<?language javascript?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.control.*?>

<fx:root type="javafx.scene.layout.VBox" xmlns:fx="http://javafx.com/fxml/1">
	<children>
	<!-- 変数宣言 -->
		<!-- リソース・バンドルの利用例  -->
		<Label fx:id="greeting" text="%message.greeting"/>
	</children>
</fx:root>

【TestFXML4_en.properties】
# 英語のメッセージ
message.greeting=hello

【TestFXML4_ja.properties】
# 日本語のメッセージ
message.greeting=こんにちは

◇実行結果
 

◇解説
 リソースバンドルの使用はTestFXML4.javaの34行目~36行目である。ResourceBundle::getBundle関数で、propertiesファイルの基底名とロケールを指定し、戻り値をFXMLLoaderの引数と渡すだけで、適切なpropertiesファイルが選ばれる。

 propertiesファイルに記述されたリソースを出力しているのは、TestFXML4.fxmlの11行目である。「%」接頭辞によりリソース使用を宣言し、続いてリソース名「message.greeting」を指定している。TestFXML4_ja.propertiesファイルを見てみると、該当のキーに対して値は「こんにちは」となっており、これが画面出力されている。propertiesファイルの書き方はstruts等と同じなので見覚えがある人も多いと思われる。基本的に「key=value」を羅列しているだけである。

 ちなみに、ResourceBundle::getBundle関数使用時にロケールをアメリカにする(TestFXML4.java:35行目の記述内容)と以下のような出力となり、propertiesファイルが正常に切り替わっていることが確認できる。




■ カスタム・コンポーネントの利用

 FXMLではカスタム・コンポーネントにより、画面とコントローラを部品化することができる。カスタム・コンポーネントの作り方は、FXMLにて部品化したい画面構成を作成し、ルートタグをfx:rootタグに置き換え、コントローラ内でfx:rootタグをコントローラ自身にマッピングするだけでいい。こうして作成されたコントローラは、別のFXMLにて<?import>タグで取り込むことが可能となる。タグ名はコントローラのクラス名になる。

■ サンプルプログラム

 カスタム・コンポーネントを作成・利用するサンプルプログラムを以下に示す。

◇リソース
TestJavaFX(プロジェクト)
 ┗ src
   ┗ application
     ┣ CustomTag.java
     ┣ TestFXML5.java
     ┣ CustomTag.fxml
     ┗ TestFXML5.fxml

◇サンプルコード
【TestFXML5.java】
package application;

import java.net.URL;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;

/**
 * FXMLファイルを利用する5
 * 
 * @author karura
 *
 */
public class TestFXML5 extends Application
{
    public static void main(String[] args) {
        launch(args);
    }
    
    @Override
    public void start(Stage primaryStage) throws Exception
    {
        // フォント色がおかしくなることへの対処
        System.setProperty( "prism.lcdtext" , "false" );
        
        // FXMLファイルの読込
        URL             location    = getClass().getResource( "TestFXML5.fxml" );
        FXMLLoader      fxmlLoader  = new FXMLLoader( location );
        
        // シーングラフの作成
        Pane    root        = (Pane) fxmlLoader.load();
        
        // シーンの作成
        Scene   scene       = new Scene( root , 200 , 50 );
        
        // ウィンドウ表示
        primaryStage.setScene( scene );
        primaryStage.show();
    
    }

}

【TestFXML5.fxml】
<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.layout.VBox?>
<?import javafx.scene.control.Label?>
<?import application.CustomTag?>

<VBox xmlns:fx="http://javafx.com/fxml/1">
	<Label text="hello world!" />
	<CustomTag />
</VBox>

【CustomTag.java】
package application;

import java.io.IOException;
import java.net.URL;

import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.layout.HBox;

/**
 * TestFXML5.fxmlのコントローラ
 * 
 * @author karura
 *
 */
public class CustomTag extends HBox
{
    
    /**
     * デフォルト・コンストラクタ
     */
    public CustomTag()
    {
        // 親のコンストラクタを起動
        super();

        // FXMLファイルの読込準備
        URL             location    = getClass().getResource( "CustomTag.fxml" );
        FXMLLoader      fxmlLoader  = new FXMLLoader( location );
        
        // FXMLのルートタグとして、自らを登録
        fxmlLoader.setRoot( this );
        fxmlLoader.setController( this );
        
        // FXMLの読込
        try{
            fxmlLoader.load();
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException( e.getMessage() );
        }
        
        // インスタンス化の確認メッセージ
        System.out.println("CustomTag instantiation!");
        
    }
    
    /**
     * Button1押下時のイベントハンドラ
     * @param e
     */
    @FXML
    public void onPushButton1( ActionEvent e )
    {
        System.out.println( "button1 was pushed!" );
    }
    
}

【CustomTag.fxml】
<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.layout.HBox?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TextField?>

<fx:root type="javafx.scene.layout.HBox" xmlns:fx="http://javafx.com/fxml/1">
	<TextField fx:id="text1" promptText="input your name" />
	<Button fx:id="button1" onAction="#onPushButton1" text="push"/>
</fx:root>

◇実行結果
CustomTag instantiation!


◇解説
 プログラムは、TestFXML5クラスを起動しFXMLLoader::load関数でTestFXML5.fxmlを読み込むところから始まる。読み込まれたTestFXML5.fxml内では、5行目で新しく作成したカスタム・コンポーネントの宣言を、9行目で新しく作成したカスタム・コンポーネントを使用している。

 TestFXML5.fxml内でCustomTagタグが呼ばれたことにより、CustomTagクラスがインスタンス化される(CustomTag.java:23行目~47行目)。コンストラクタ内部では、CustomTag.fxmlが読み込まれ、HBoxを継承したCustomTagクラスがルートノードに設定される(CustomTag.java:33行目)。同時にコントローラとしても登録することで、CustomTag.fxmlで作成されたボタンなどのオブジェクトやイベント・ハンドラとマッピングが行われている(CustomTag.java:34行目)。

 そして、CustomTagタグの読み込みが完了し、TestFXML5.fxml自体の読み込みも完了するカスタム・コンポーネントであるCustomTag(テキスト入力欄とボタン)が画面に表示されていることが確認できる。「push」ボタンを押下すると、イベントハンドラCustomTag::onPushButton1(CustomTag.java:54行目~57行目)が起動され、標準出力に文字が出力されることが確認できる。

 例えば、このCustomTagタグを配布する場合には、CustomTag.javaとCustomTag.fxmlの両方を配布すればよい。


■ 参照

  1. JavaDoc「クラス ResourceBundle - getBundle」
  2. JavaDoc「クラス Locale」
  3. Vladislav Korecký「How to create JavaFX FXML custom component」
Home > JavaFX入門 > FXMLを利用する(2)リソースバンドル/カスタムコンポーネント

- ランダム記事 -
- PR -

コメント

プロフィール

管理者:
 連絡はContactよりお願いします。

PR