読者です 読者をやめる 読者になる 読者になる

ひらおかゆみのなげやりブログ

もう、なげやりです…

JavaFXのユーティリティたち

ハッピーバースデー、私!

ということで22歳になりました。

いや、本当のところはJavaFX Advent Calendar・19日目のエントリです。昨日、18日目は櫻庭さん (@skrb) のエントリ「バインドのサンプル」です。

今日は当たり前すぎて誰も見向きもしてくれない縁の下の力持ち(?)、JavaFXのユーティリティたちにスポットライトを当てます。光を当ててもやっぱり暗い、小惑星のようなクラスたちです。JavaFX歴5日の私には皆さんのようにすごいものは作れませんが、私にできる精一杯のことをやってみました。

 

§1. StringConverter

JavaFXにはStringConverterとそのサブクラスがたくさん用意されています。簡単に言うとこれまでFormatクラスがやっていたことを実現するだけのクラスです。しかもFormatを置き換えるわけではなく、内部で使っていたりします。違いといえば、parse/formatメソッドの代わりにfromString/toStringメソッドを使うことと、文字列を解析するメソッド(fromString)がチェック例外を投げないことでしょうか。StringConverterはabstract宣言されているので、実際には以下のサブクラスを利用します。

基本:

特殊な数値:

日付・時刻:

汎用:

特殊:
FormatStringConverterとNumberAxis.DefaultFormatterを除きデフォルトコンストラクタを持ちます。また、特殊な数値と日付・時刻用のものはパターンの文字列やロケールでフォーマットを指定できます。FormatStringConverterは指定するFormatオブジェクト次第でどんな変換にも対応します。

 表示サンプルのプログラムを以下に示します。

[DateTimeConverters.java]

package org.yumix.javafxutil.converter;

import java.util.*;

import javafx.scene.paint.*;
import javafx.util.converter.*;

public class DateTimeConverters {

  public static void main(String args) {
    // 2012/12/19 14:46:00 JST
    Date now = new Date(1355895960000L);
    
    // Date
    DateStringConverter dsc = new DateStringConverter();
    System.out.println("Date");
    System.out.println(dsc.toString(now));
    System.out.println(dsc.fromString("2012/12/19"));
    
    // Date and Time
    DateTimeStringConverter dtsc = new DateTimeStringConverter();
    System.out.println("\nDate and Time");
    System.out.println(dtsc.toString(now));
    System.out.println(dtsc.fromString("2012/12/19 14:46:00"));
    
    // Time
    TimeStringConverter tsc = new TimeStringConverter();
    System.out.println("\nTime");
    System.out.println(tsc.toString(now));
    System.out.println(tsc.fromString("14:46:00"));
    
    // Date and Time (ISO)
    DateTimeStringConverter isodtsc = new DateTimeStringConverter("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
    System.out.println("\nDate and Time (ISO)");
    System.out.println(isodtsc.toString(now));
    System.out.println(isodtsc.fromString("2012-12-19T14:46:00.000+09:00"));
  }
	
}

[NumberConverters.java]

package org.yumix.javafxutil.converter;

import java.util.*;

import javafx.util.converter.*;

public class NumberConverters {

  public static void main(String args) {
    // Number
    NumberStringConverter nsc = new NumberStringConverter();
    System.out.println("Number");
    System.out.println(nsc.toString(10));
    System.out.println(nsc.fromString("10"));
    
    // Currency
    CurrencyStringConverter csc = new CurrencyStringConverter();
    System.out.println("\nCurrency (Default)");
    System.out.println(csc.toString(1200));
    System.out.println(csc.fromString("¥1,200"));
    
    // Currency (U.S.)
    CurrencyStringConverter uscsc = new CurrencyStringConverter(Locale.US);
    System.out.println("\nCurrency (U.S.)");
    System.out.println(uscsc.toString(1200));
    System.out.println(uscsc.fromString("$1,200.00"));
    
    // Currency (Germany)
    CurrencyStringConverter gercsc = new CurrencyStringConverter(Locale.GERMANY);
    System.out.println("\nCurrency (Germany)");
    System.out.println(gercsc.toString(1200));
    System.out.println(gercsc.fromString("1.200,00 €"));
    
    // Percentage
    PercentageStringConverter psc = new PercentageStringConverter();
    System.out.println("\nPercentage");
    System.out.println(psc.toString(0.15));
    System.out.println(psc.fromString("15%"));
  }

}

完全な形のソースコードEclipseプロジェクト・e(fx)clipse必須)はGitHubにあります。

https://github.com/yumix/JavaFXUtilities 

 

§2. Builder

JavaFXにはUIパーツを中心になんとかBuilderというクラスがたくさんあります。これらはすべてBuilderインタフェースを実装していて、どのBuilderでも操作が統一されるようにできています。たとえば、こんな感じ:

Color color = ColorBuilder.create().green(0.5).blue(0.75).build();

Builderはクラスによって操作がまちまちで、たとえばStringBuilderはtoStringメソッドでStringを返すけれども、JerseyのWebResourceは場面によってget、post、put、delete、head、optionsと固めるメソッドが違うケースもあります。少なくともJavaFXではその辺が統一され、JavaFXBuilderFactoryクラスでBuildしたいクラスからBuilderを取得できるようにもなっています。自分でBuilderを作るときにも、JavaFXのBuilderインタフェースを実装しておけば他のBuilderと同様に扱えるし、使う側にとっても同じ操作はメリットが大きいはずです。

  

§3. Callback

Builderは実も蓋もない言い方をすれば「だから何なんだ?」的なものでしたが、これから取り上げるCallbackはそれ以上に「だから何なんだ?」的なものです。こんなものいちいち標準化しなければいけないのか?

Javaでコールバック関数を実装するときは、だいたい誰が書いても同じように、単純なインタフェースを実装した匿名のインナークラスを使うと思います。こういうときに限って自力で良い例が思いつかなかったので、1日目の @aoe_tk さんのコードを拝借します: 

pagenation.setPageFactory(new Callback() {
  @Override
  public Node call(Integer idx) {
    return createPage(idx);
  }
});

いきなりですが、Java 8のLambdaを使うと、たぶんこうなります(あくまで想像):

pagenation.setPageFactory(idx -> createPage(idx)); 

(最初、Lambdaに書き直してみたとき、あまりに出来過ぎていると思いました…)

あくまで私の勝手な予測ですが、CallbackインタフェースはLambdaを見越して用意しているのでしょう。Lambdaで書けるインタフェースには制約があるので、あらかじめ制約を満たすように標準化したのでしょう。

参考 Lambdaへの道 http://www.slideshare.net/skrb/lambda-15544054

 

おわりに

JavaFXというと華やかなCGや美しいUIばかりに目が向きがちですが、それらを陰で支える小さなクラス・インタフェースがあって成り立っているものだと思います。

明日は @cocoatomo さんです。