倭マン's BLOG

くだらない日々の日記書いてます。 たまにプログラミング関連の記事書いてます。 書いてます。

はじめての幻獣 Griffon 研 (32) : グラフを PNG ファイルとして保存する

JFreeChart でグラフを描画できるようになったら、やっぱり画像ファイルとして保存したいよね!ってことで、今回はファイル保存機能を追加(一覧)。

JFreeChart のグラフを画像ファイルとして保存する方法と、JFileChooser の使い方は以下の記事参照:

サンプルは簡単のため画像ファイルとして PNG ファイルのみを扱うことにします。 また、ファイルの上書きなどの確認も行っていません。 ちなみに、JFreeChart の ChartPanel はデフォルトでファイル保存機能をサポートしてますが(ポップアップメニューから実行可能)、ここではその機能は知らない体でやっていきます:-)

FunctionPlotterController


View やアクションの定義は一辺倒なので省略。 で、Controller にファイル保存機能を saveChart として実装します:

package functionplotter

import javax.swing.JFileChooser
import javax.swing.filechooser.FileNameExtensionFilter
import org.jfree.chart.ChartUtilities

class FunctionPlotterController {

    def model
    def view
    def builder

    def saveChart = { evt = null ->
        def fc = builder.fileChooser(fileSelectionMode: JFileChooser.FILES_ONLY,
                                               dialogTitle:'Select Image File',
                                               fileFilter:new FileNameExtensionFilter('*.png', 'png'))
    	if (fc.showSaveDialog() == JFileChooser.APPROVE_OPTION){
            def file = fc.selectedFile
            def panel = view.coordinate
            ChartUtilities.saveChartAsPNG(file, panel.chart, panel.width, panel.height)
        }
    }
}

JFileChooser オブジェクトは builder フィールド(自動でビルダーオブジェクトがセットされます)を使って取得します。 それ以外は通常の JFileChooser オブジェクトの使い方と同じです。 JFreeChart のグラフを描画するには ChartUtilities クラスの static メソッド saveChartAsPNG() を使います。

さて、これで問題ないと言えばないんですが、実際にこの実装をして動作させてみると、最初にダイアログを表示させるときにやたらと時間がかかってしまいます。 2度目以降は問題なく動作するので、最初の起動の際に初期化処理で時間がかかってしまうようです。 なので、次にその改善方法を見ていきます。

パフォーマンスを改善


ここで見ていくパフォーマンス改善策は、アプリケーションの起動時に JFileChooser の初期化も一緒にやってしまおう!って方法です*1

FunctionPlotterView

JFileChooser の初期化をアプリケーション起動時に行うには、View の application ノード外に fileChooser ノードを記述して JFileChooser オブジェクトを View に保持させるようにします:

package functionplotter

import javax.swing.filechooser.FileNameExtensionFilter

application(...){...}

fileChooser(id:'fc', 
                 fileSelectionMode: JFileChooser.FILES_ONLY,
                 dialogTitle:'Select Image File',
                 fileFilter:new FileNameExtensionFilter('*.png', 'png'))

この JFileChooser は Controller から参照したいので、id を付与しておきます。 もしくは id を指定せずに

fc = fileChooser(...)

としても構いません。 ただし def キーワードはつけないようにしましょう。

FunctionPlotterController

JFileChooser オブジェクトの準備は View で行われるので、Controller ではそれ以外の「ダイアログの表示」と「結果による処理」を行います:

package functionplotter

import javax.swing.JFileChooser
import org.jfree.chart.ChartUtilities

class FunctionPlotterController {

    def model
    def view

    def saveChart = { evt = null ->
    	if (view.fc.showSaveDialog() == JFileChooser.APPROVE_OPTION){
            def file = view.fc.selectedFile
            def panel = view.coordinate
            ChartUtilities.saveChartAsPNG(file, panel.chart, panel.width, panel.height)
        }
    }
}

View に定義した JFileChooser オブジェクトは view.fc によって取得できます。 それ以外の処理は前のサンプルと同じです。

この方法だとアプリケーション起動時に JFileChooser の初期化も行われるので起動時間が少々長くなってしまいます。 なので、ファイルアクセスをあまり行わないアプリケーションではあまり使わない方がよいかも知れません。 ただし、実際には起動時間の延長がそんなに気にならないので(アプリケーションの起動自体がそれなりに時間がかかる)、JFileChooser を使う場合は大抵この方法を使って問題ないと思います。

Griffon in Action

Griffon in Action


Groovyイン・アクション

Groovyイン・アクション

*1:Griffon に付属しているサンプルを参考にしています:FileViewer