- PR -

JFreeChart複合グラフ表示について

1
投稿者投稿内容
n.w
大ベテラン
会議室デビュー日: 2003/07/15
投稿数: 126
お住まい・勤務地: 神奈川
投稿日時: 2004-11-12 10:54
お世話になってます。
現在、JFreeChartを使い棒グラフと折れ線グラフの
複合グラフを作成しています。
表自体はできたのですが、グラフのY軸データが
棒グラフと折れ線グラフで整合がとれず苦戦しています。
グラフイメージは下記のようにしていますが、
※1と※2で棒グラフと折れ線グラフが別物として
表示されてしまいます。
方法としては合わせるか※2を表示せず
棒グラフ内に折れ線グラフを乗せるしかないのかと
思って色々調べてみたのですが、わからない状態です

方法を又は参考サイトなど教えてもらえると幸いです。

コード:
 

※1 ※2
200 | |120
  | グラフ |
100 | |60
  | |
0  | |0
−−−−−−−−−−−−−−−



コード:

public class BarChartDemoFinel extends ApplicationFrame {

private String[] categorys = {
"4月","5月","6月","7月","8月","9月","10月","11月","12月","1月","2月","3月"
};

private String series1 = "2002年度データ";
private String series2 = "2003年度データ";
private String series3 = "2004年度データ";

public BarChartDemoFinel(String title) {

super(title);

CategoryDataset dataset = createDataset();
JFreeChart chart = createChart(dataset);
ChartPanel chartPanel = new ChartPanel(chart);
chartPanel.setPreferredSize(new Dimension(500, 270));
setContentPane(chartPanel);

}

private CategoryDataset createDataset() {
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
for(int i=0; i<12; i++){
dataset.addValue(17000+300*i, series1, categorys[i]);
dataset.addValue(18000+300*i, series2, categorys[i]);
dataset.addValue(20000+300*i, series3, categorys[i]);
}
return dataset;
}

private JFreeChart createChart(CategoryDataset dataset) {

// create the chart...
JFreeChart chart = ChartFactory.createBarChart(
"Test", "", "", dataset, PlotOrientation.VERTICAL,
true, true, false
);

// 図表用に背景色をセット
chart.setBackgroundPaint(new Color(0xBBBBDD));

// 一層のカスタマイゼーションのためにプロット取得
CategoryPlot plot = chart.getCategoryPlot();

// 範囲軸に整数だけを表示
NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());

BarRenderer renderer = (BarRenderer) plot.getRenderer();
renderer.setDrawBarOutline(false);

CategoryAxis domainAxis = plot.getDomainAxis();
domainAxis.setCategoryLabelPositions(CategoryLabelPositions.UP_90);
domainAxis.setMaxCategoryLabelWidthRatio(5.0f);

CategoryDataset dataset2 = createDataset2();
ValueAxis axis2 = new NumberAxis();
plot.setRangeAxis(2, axis2);
// 折れ線グラフデータ設定
plot.setDataset(2, dataset2);
// グラフ軸調整
plot.mapDatasetToRangeAxis(2, 2);

// 折れ線グラフ作成
CategoryItemRenderer renderer2 = new LineAndShapeRenderer();
renderer2.setSeriesPaint(0, Color.YELLOW);
plot.setRenderer(2, renderer2);
plot.setDatasetRenderingOrder(DatasetRenderingOrder.REVERSE);
return chart;
}

private CategoryDataset createDataset2() {
// CategoryDatasetインターフェースのデフォルト・インプリメンテーション。
// データ格納クラス構築
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
for(int i=0; i<12; i++){
dataset.addValue(10000, series3, categorys[i]);
}
return dataset;
}


public static void main(String[] args) {
BarChartDemoFinel demo = new BarChartDemoFinel("Test");
demo.pack();
RefineryUtilities.centerFrameOnScreen(demo);
demo.setVisible(true);
}
}



[ メッセージ編集済み 編集者: n.w 編集日時 2004-11-12 11:06 ]
n.w
大ベテラン
会議室デビュー日: 2003/07/15
投稿数: 126
お住まい・勤務地: 神奈川
投稿日時: 2004-11-12 11:25
自己レスです。
解決しました。

ValueAxis#setMaximumAxisValue(double max)
を使用し折れ線、棒グラフ共通の最大値を作成することで
きれいにだす事ができました。
ただsetMaximumAxisValueは推奨されておらず
setUpperBoundメソッドを使用した方がいいみたいです。
が、まだ試してません。

na2fusi
会議室デビュー日: 2003/06/08
投稿数: 16
投稿日時: 2004-11-12 12:19
createChartメソッドを以下のように修正すれば良いかと思います。
グラフの種類が違うからといって
plot.setDataset(int,Dataset)やplot.setRenderer(int,Renderer)の
第一引数に異なる数値を渡す必要はありません。
異なる数値を渡すと別々のグラフを一つに重ねたものとして解釈されます。

棒グラフの後ろに折れ線グラフを配置すると醜いので
折れ線グラフを棒グラフの前にしたほうがいいかもしれませんね。

コード:
    private JFreeChart createChart(CategoryDataset dataset) {
    ・・・
        CategoryDataset dataset2 = createDataset2();
//	 ValueAxis axis2 = new NumberAxis();

//	 plot.setRangeAxis(2, axis2);
	 plot.setRangeAxis(1, rangeAxis);←※2側にも値を表示したい場合のみ必要
	 // 折れ線グラフデータ設定
//	 plot.setDataset(2, dataset2);
	 plot.setDataset(1, dataset2);
        // グラフ軸調整
        plot.mapDatasetToRangeAxis(2, 2);←不必要
        
        // 折れ線グラフ作成
        CategoryItemRenderer renderer2 = new LineAndShapeRenderer();
        renderer2.setSeriesPaint(0, Color.YELLOW);
//      plot.setRenderer(2, renderer2);
       plot.setRenderer(1, renderer2);
        plot.setDatasetRenderingOrder(DatasetRenderingOrder.REVERSE);
        return chart;
    }




引用:

コード:
 
 ※1                       ※2
200 |                    |120
  |      グラフ        |
100 |                    |60
  |                    |
0  |                    |0
−−−−−−−−−−−−−−−



n.w
大ベテラン
会議室デビュー日: 2003/07/15
投稿数: 126
お住まい・勤務地: 神奈川
投稿日時: 2004-11-12 13:22
na2fusi様、ありがとうございます。
ご指摘の点も含めグラフをきれいに出すことができました。

ただ気になったのですが、ChartFactoryで作成したグラフと
CategoryItemRenderer renderer2 = new BarRenderer();
にて作成したグラフではChartFactoryで作成したグラフの方が
優先度(?)が高い為ChartFactoryで折れ線グラフを作ったのですが

※3位置に出るグラフの説明欄の順番折れ線を一番右にしたい
場合など調節が効かない作りになってしまいます。
回避策としてはLegendクラスのメソッドなど駆使して並び替えるなどを
行うべきでしょうか?


コード:

200 | |120
  | グラフ |
100 | |60
  | |
0  | |0
−−−−−−−−−−−−−−−
※3 XXXXXXXXX



コード:

private JFreeChart createChart(CategoryDataset dataset) {

JFreeChart chart = ChartFactory.createLineChart(
"Test", "", "", dataset, PlotOrientation.VERTICAL,
true, true, false
);

// 図表用に背景色をセット
chart.setBackgroundPaint(new Color(0xBBBBDD));

CategoryPlot plot = chart.getCategoryPlot();

NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());

LineAndShapeRenderer renderer = (LineAndShapeRenderer)plot.getRenderer();
renderer.setSeriesPaint(0, Color.orange);

CategoryAxis domainAxis = plot.getDomainAxis();
domainAxis.setCategoryLabelPositions(CategoryLabelPositions.UP_90);
domainAxis.setMaxCategoryLabelWidthRatio(5.0f);

CategoryDataset dataset2 = createDataset();
plot.setDataset(1, dataset2);

// 棒グラフ作成
CategoryItemRenderer renderer2 = new BarRenderer();
renderer2.setSeriesPaint(0, Color.lightGray);
renderer2.setSeriesPaint(1, Color.gray);
renderer2.setSeriesPaint(2, Color.blue);
plot.setRenderer(1, renderer2);
plot.setDatasetRenderingOrder(DatasetRenderingOrder.REVERSE);

return chart;
}




[ メッセージ編集済み 編集者: n.w 編集日時 2004-11-12 13:35 ]

[ メッセージ編集済み 編集者: n.w 編集日時 2004-11-12 13:37 ]
na2fusi
会議室デビュー日: 2003/06/08
投稿数: 16
投稿日時: 2004-11-12 16:13
引用:

n.wさんの書き込み (2004-11-12 13:22) より:
ただ気になったのですが、ChartFactoryで作成したグラフと
CategoryItemRenderer renderer2 = new BarRenderer();
にて作成したグラフではChartFactoryで作成したグラフの方が
優先度(?)が高い為ChartFactoryで折れ線グラフを作ったのですが


折れ線グラフが棒グラフの後ろに隠れてしまうことを優先度が高いとおっしゃっていますか?
折れ線グラフが棒グラフの後ろに隠れてしまったのは
plot.setDatasetRenderingOrder(DatasetRenderingOrder.REVERSE);の引数です。
詳しくはjfreechartのAPIを読んでください。
引用:

※3位置に出るグラフの説明欄の順番折れ線を一番右にしたい
場合など調節が効かない作りになってしまいます。
回避策としてはLegendクラスのメソッドなど駆使して並び替えるなどを
行うべきでしょうか?



何も指定しないとデフォルトの設定が適用されます。
フレームのサイズやLegendの位置、フォントのサイズも影響しています。
もしLegendの並び替えや中身をいじりたいなら
plot.getLegendItemsでLegendItemCollectionを取得
plot.setFixedLegendItemsでセットするとよいでしょう。
(私はLegendの中身をいじったことがないのでこの程度しか答えられません。)
レイアウトの設定はいろいろできるかと思いますのでAPIのドキュメントと
にらめっこしながら納得のいくものを作ってみてください。
n.w
大ベテラン
会議室デビュー日: 2003/07/15
投稿数: 126
お住まい・勤務地: 神奈川
投稿日時: 2004-11-17 20:55
na2fusi様ありがとうございました。
無事思ったとおりのグラフを作成することができました。

APIのドキュメントエキサイト翻訳でひたすら訳して
はいたんですが、はまってしまっていました
やはり英語は必須だなと痛感した今日この頃です。

JFreeChartの細かい点はいじくり倒してみようと思います。
1

スキルアップ/キャリアアップ(JOB@IT)