マルチプラットフォームで動作可能な,データ可視化アプリを作る必要に迫られたのでJavaFXを使ってみようかなとか.で,2012年くらいに使ってみた以来,久しぶりにJavaFXを使ってみたら,いろいろと嬉しい驚きが.
「データ可視化アプリ作るならPython + matplotlibでいいじゃん」
って言う人がまわりにたくさんいるので,少しでも対抗できるように,まずは,そこそこ奇麗なグラフの描画と各種フォーマットでの保存方法を調査.
コードは https://github.com/miyo/javafx_test/tree/master/SimpleCalc に.
SimpleCalcという名前に反して,電卓機能はもっていません.数字キーをクリックすると適当にチャートやらCanvasやらにデータが挿入されます.コード片はWorking with JavaFX Chartから拝借.適当に描画した後で,Saveをクリックすると,全チャートとCanvasのデータがpng,jpeg,PDFで保存される,実験のためのコードです.
GUIの枠組み
SceneBuilderで作れば楽ちん.いろいろ考えるとややこしいのでしょうけど.
肝は,
(1)Javaコードで操作対象にしたいオブジェクトにはIDをつけておく
(2)GUIコンポーネントへの操作をJavaプログラムに通知したければハンドラなメソッド名を定義しておく,
の二つ.
グラフとかイメージの描画
グラフはデータをつっこめばいい.XYChartのペアが文字だったり数字だったりするのはSceneBuilder側で決められるのかな?コードで生成するときは指定できるみたいだけど...とりあえず怒られないように設定.
表示イメージを取得
チャートやCanvasなどの親クラスなNodeに定義されたsnapshotで,WritableImageというデータが取得できる.
以上.
従来の画像操作ライブラリで操作するときにBufferedImageに変換したければ,SwingFXUtils.fromFXImageを使えばいいみたい.ちなみに逆のtoFXImageも用意されている.
イメージをファイルに保存
JavaFXというかImageIOすばらしい,という話.JavaFX 2 Snapshot as PNG Imageにズバリ書いてありました.
private boolean saveImage(WritableImage img, String base, String fmt) throws IOException{
File f = new File(base + "." + fmt);
return ImageIO.write(SwingFXUtils.fromFXImage(img, null), fmt, f);
}
fmtには,文字列でpngとかjpgとかを指定.指定できないフォーマット,たとえばpdfとか指定すると返戻値としてfalseが帰ってくる.
PDFに保存
PDFBoxを使うのが簡単みたい.2.0.0-RC2を試してみました.ちなみに,実行時にApache Commons Loggingへのパスが通ってないとエラーになるので注意が必要(Loggingがなくてもコンパイルはとおる).
コードはこんな感じ.
private void saveAsPDF(WritableImage img, String base) throws IOException{
PDDocument doc = null;
PDPage page = null;
PDImageXObject ximage = null;
try {
doc = new PDDocument();
page = new PDPage();
doc.addPage(page);
PDPageContentStream content = new PDPageContentStream(doc, page);
ximage = LosslessFactory.createFromImage(doc, SwingFXUtils.fromFXImage(img, null));
content.drawImage(ximage, 20, 20);
content.close();
} catch(IOException ie) {
}
doc.save(new File(base + ".pdf"));
doc.close();
}
Webで検索してでてくる,PDFBox2.0.0以前のサンプルではPDImageXObjectじゃなくてPDXObjectImageになっているので注意.たとえばAdd BufferedImage to PDFBox documentのコードとか.
移行方法についてはMigration to PDFBox 2.0.0に書いてある.
とりあえず保存できたけど,サイズを考慮してなくて端が欠けるのは,どうにかしないとね.