ファイヤープロジェクト
グラフデータの更新(JFreechart 0.9.16)
2004-02-21T18:45+09:00   matsu
JFreeChartでグラフデータを定期的に更新して,ウィンドウ表示されるグラフも更新する方法を調査してみた.
今回のサンプルは,ある時間毎に/proc/statからCPU使用時間を読み取って(※),CPU使用率を計算して下のようなメーターを表示するものである.
以降,これを便宜上MeterChartと呼ぶ.ではサンプルのコード.
このコードは自作のDatasetであるCPUDataに依存する.
今回の登場クラスについて整理しておく.
※ 当然ながらprocファイルシテステムがないシステムでは正しく動作しないと思う.
サンプルではMeterChartはSampleMeterChartクラスのcreateChartメソッドで行なっている.ChartFactoryはMeterChartの作成メソッドを提供していないので(※),JFreeChartのコンストラクタを直接呼び出して作成する.
chart = new JFreeChart("SysMon", JFreeChart.DEFAULT_TITLE_FONT, plot, false);
ここで始めてJFreeChartのコンストラクタが登場した.パラメータについて書いておく.
第一引数
Chartのタイトル.
第二引数
Chartのタイトル表示に使用するフォント.
第三引数
Plot.
第四引数
Legendを作成するか否か.
第三引数はPlotで,MeterChartではPlotのサブクラスであるMeterPlotが必要であるので,JFreeChartのコンストラクタ呼び出しの前にあらかじめ作成した.
data = new CPUData();
MeterPlot plot = new MeterPlot(data);
MeterPlotはValueDatasetを必要とする.今回はこの実装クラスCPUDataを自作した.詳細は次節.createChartメソッドではさらにMeterChartに対してサブタイトルを設定している.
chart.addSubtitle(new TextTitle("CPU"));
引数はTextTitleである.サブタイトルは複数設定可能でsetSubtitlesというメソッドが提供されているが,addSubtitleは名前のとおり追加を意味する.
※ 理由はおそらくFactoryパターンを適用するほど複雑な処理を必要としていないからだろう.
SampleMeterChartでは,メソッドworkの無限ループで,一定時間おきにMeterChartのデータのupdateメソッドを呼び出している.
while (true) {
    data.update();
    try {
	Thread.sleep(interval);
    } catch (InterruptedException e) {
	e.printStackTrace();
	System.exit(-1);
    }
}
udateメソッドは自作クラスCPUDataで実装した.このupdateメソッドを呼び出すことによって,Frameのメータが逐次更新されるようにした.updateメソッドでは,procファイルを読み取り,CPU使用率を計算する(※).そして計算結果からCPU使用率が更新されたかどうかを判断し,以下を実行する.
notifyListeners(new DatasetChangeEvent(this, this));
このメソッドはCPUDataのスーパークラスDefaultValueDatasetから継承した.詳細は次節.とにかくこれを呼べばChartPanelは再描画する.ただし,notifyListenersはprotectedである.今回はDatasetであるCPUDataが自発的にそれを呼び出すように作成したが,場合によっては上位で既存のDatasetを使用してデータを更新し,それから上位から再描画を指示したい場合もある.そのような場合は,JFreeChartの以下のメソッドを呼び出す.
fireChartChanged() 
これはJFreeChartでパネルに再描画を促すもっとも基本的な方法である.
※ 詳細はJFreeChartと直接関係ないので省略.
サンプルにおけるJFreeChartの構造をEventListenerの視点からざっくり見てみると,以下のようなクラス図が書ける.
EventListenerの視点から見ると,今までとは逆にPlotはJFreeChartを,ChartFrameはJFreeChartを保持している.そして,それぞれが持つxxxChangedメソッド呼び出しにより,保持しているオブジェクトに対して自分が変更されたことを伝える.以下はサンプルにおけるCPUDataの変更の伝播の様子である.
CPUDataは保持しているDatasetChangeListenerであるMeterPlotに対して自分が変更されたことを伝える.従来の見方だとMeterPlotはDatasetであるCPUDataを保持しているので,CPUDataが変更されたということは,JFreeChartにとってはMeterPlotは変更されたことになる.したがってMeterPlotはJFreeChartに自分が変更されたことを伝える(plotChangedメソッド呼び出し).同様にJFreeChartはChartFrameに自分が変更されたことを伝える(※).この仕組みによりCPUDataのupdateメソッド内でnotifyListenersを呼び出すと,最終的にデータの変更がChartFrameに伝えられ,再描画が行なわれる.また,JFreeChartの以下のメソッドでも,内部でChartFrameのchartChangedメソッドが呼び出され,ChartFrameの再描画を促す.
fireChartChanged() 
※ Chain of responsibilityパターン.
matsu(C)
Since 2002
Mail to matsu