LoginSignup
12
14

More than 5 years have passed since last update.

JavaFX8で表示したイメージをファイルに保存する

Last updated at Posted at 2015-12-14

マルチプラットフォームで動作可能な,データ可視化アプリを作る必要に迫られたので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に書いてある.
とりあえず保存できたけど,サイズを考慮してなくて端が欠けるのは,どうにかしないとね.

ちなみに,こんな感じ

javafx_test.PNG
冒頭にも書いた通り,実験のためのプログラムなので意味はありません.

12
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
14