|
|
JFreeChart を使ったグラフ作成 ガントチャート(GanttChart) |
H.Kamifuji . |
ガントチャート(GanttChart)の作成に関して確認します。ガントチャートはプロジェクト管理などで使用されるグラフで作業項目と作業日程などを軸に取り作業進捗を管理するために使用します。 当ページでは、Linux CentOS7 の Gnome で動作テストしています。 現在(2021/08)では、JDK-16.0.2 にアップされています。一部、上位互換について、見直しを行っていきます。 現在(2023/04)では、JDK-20.0.1 にアップされています。一部、上位互換について、見直しを行っていきます。 現在(2024/10)では、JDK-23 に、アップされています。JDK-23 + jfreechart-1.0.19 で、上位互換について、見直しを行っていきます。 |
|
ガントチャートの基本的な作成方法を確認します。 まずChartFactoryクラスの「createGanttChart」メソッドを使ってガントチャートを扱うJFreeChartクラスのオブジェクトを作成します。 createGanttChart public static JFreeChart createGanttChart(java.lang.String title, java.lang.String categoryAxisLabel, java.lang.String dateAxisLabel, IntervalCategoryDataset dataset, boolean legend, boolean tooltips, boolean urls)Creates a Gantt chart using the supplied attributes plus default values where required. The chart object returned by this method uses a CategoryPlot instance as the plot, with a CategoryAxis for the domain axis, a DateAxis as the range axis, and a GanttRenderer as the renderer. Parameters: title - the chart title (null permitted). categoryAxisLabel - the label for the category axis (null permitted). dateAxisLabel - the label for the date axis (null permitted). dataset - the dataset for the chart (null permitted). legend - a flag specifying whether or not a legend is required. tooltips - configure chart to generate tool tips? urls - configure chart to generate URLs? Returns: A Gantt chart. 1番目の引数にグラフのタイトルを文字列で指定します。 2番目の引数には項目を表す軸のラベルを文字列で指定します。Y軸に設定されます。3番目の引数には日付を表す軸のラベルを文字列で指定します。X軸(上部)に設定されます。 4番目の引数にはグラフのデータをIntervalCategoryDatasetインターフェースを実装したクラスのオブジェクトで指定します。今回はTaskSeriesCollectionクラスを使います。詳細は次のページで確認します。 5番目の引数には凡例を表示するかどうかを「true」か「false」で指定します。 6番目の引数にはツールチップを作成するかどうかを「true」か「false」で指定します。 7番目の引数にはURLを作成するかどうかを「true」か「false」で指定します。 実際の使い方は次のようになります。 TaskSeriesCollection data = new TaskSeriesCollection(); JFreeChart chart = ChartFactory.createGanttChart("プロジェクト管理", "項目", "日程", data, true, false, false);実際のデータの追加方法は次のページで確認します。 では簡単なサンプルを作成して試してみます。 サンプルプログラム下記のサンプルを実行してみよう。/** * ガントチャートの作成(createGanttChartメソッド) */ import org.jfree.chart.JFreeChart; import org.jfree.chart.ChartFactory; import org.jfree.data.gantt.TaskSeriesCollection; import javax.swing.JFrame; import java.awt.BorderLayout; import org.jfree.chart.ChartPanel; public class Test1_1 extends JFrame{ public static void main(String[] args) { Test1_1 frame = new Test1_1(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setBounds(10, 10, 500, 500); frame.setTitle("グラフサンプル"); frame.setVisible(true); } Test1_1(){ TaskSeriesCollection data = new TaskSeriesCollection(); JFreeChart chart = ChartFactory.createGanttChart("プロジェクト管理", "項目", "日程", data, true, false, false); ChartPanel cpanel = new ChartPanel(chart); getContentPane().add(cpanel, BorderLayout.CENTER); } }上記をコンパイルした後で実行すると次のように表示されます。 ![]() |
ガントチャートではタスク系列を作成し個々のタスクをタスク系列に登録していきます。タスク系列は例えば計画と実績といったようにガントチャート上で同じタスクに対して値を表示する場合に使います。そして系列毎に個々のタスクを登録していきます。タスクはタスクの説明と開始時期そして終了時期で構成されます。最後に全てのタスク系列をタスク系列コレクションに追加します。 まずはタスク系列コレクションを表すTaskSeriesCollectionクラスのオブジェクトを作成します。 TaskSeriesCollectionクラスのクラス図は次のようになっています。 java.lang.Object | +- org.jfree.data.general.AbstractDataset | +- org.jfree.data.general.AbstractSeriesDataset | +- org.jfree.data.gantt.TaskSeriesCollection public class TaskSeriesCollection extends AbstractSeriesDataset implements GanttCategoryDataset, java.lang.Cloneable, org.jfree.util.PublicCloneable, java.io.Serializableコンストラクタは1つ用意されています。デフォルトのコンストラクタは次のようになっています。 TaskSeriesCollection public TaskSeriesCollection()Default constructor. 次のようにオブジェクトを作成します。 TaskSeriesCollection data = new TaskSeriesCollection();これでタスク系列を管理するオブジェクトが作成できました。次にタスク系列を作成します。 タスク系列の登録タスク系列はTaskSeriesクラスを使います。クラス図は次のようになっています。java.lang.Object | +- org.jfree.data.general.Series | +- org.jfree.data.gantt.TaskSeries public class TaskSeries extends SeriesTaskSeriesクラスのコンストラクタは1つ用意されています。 TaskSeries public TaskSeries(java.lang.String name)Constructs a new series with the specified name. Parameters: name - the series name (null not permitted). タスク系列の名前を引数に指定してオブジェクトを作成します。TaskSeriesクラスのオブジェクトを作成したら、TaskSeriesCollectionクラスで用意されている「add」メソッドを使ってタスク系列を追加していきます。 add public void add(TaskSeries series)Adds a series to the dataset and sends a DatasetChangeEvent to all registered listeners. Parameters: series - the series (null not permitted). 実際には次のように記述します。 TaskSeriesCollection data = new TaskSeriesCollection(); TaskSeries series = new TaskSeries("予定"); data.add(series);これでタスク系列が出来ました。最後にタスク系列に個々のタスクを登録していきます。 タスクの登録タスクはTaskクラスを使います。Taskクラスのクラス図は次のようになっています。java.lang.Object | +- org.jfree.data.gantt.Task public class Task extends java.lang.Object implements java.lang.Cloneable, org.jfree.util.PublicCloneable, java.io.SerializableTaskクラスのコンストラクタは2つ用意されています。今回は1つ目のコンストラクタを確認します。 Task public Task(java.lang.String description, java.util.Date start, java.util.Date end)Creates a new task. Parameters: description - the task description (null not permitted). start - the start date (null not permitted). end - the end date (null not permitted). 1番目の引数にはタスクの説明、2番目の引数にはタスクの開始日時、3番目の引数にはタスクの終了時期を指定します。 タスク系列に追加するタスクを必要なだけ作成したら、タスク系列に追加していきます。TaskSeriesクラスで用意されている「add」メソッドを使います。 add public void add(Task task)Adds a task to the series and sends a SeriesChangeEvent to all registered listeners. Parameters: task - the task (null not permitted). 実際には次のように記述します。 TaskSeriesCollection data = new TaskSeriesCollection(); TaskSeries series = new TaskSeries("予定"); Calendar calendar = Calendar.getInstance(); calendar.set(2007, 1, 1); Date start = calendar.getTime(); calendar.set(2007, 1, 14); Date end = calendar.getTime(); Task task = new Task("要件定義", start, end); data.add(series);では実際のデータを使って登録してみます。今回は次のようなデータを使用します。
実際には次のように記述します。 TaskSeriesCollection data = new TaskSeriesCollection(); TaskSeries series = new TaskSeries("予定"); Calendar calendar = Calendar.getInstance(); calendar.set(2007, 3, 4); Date start = calendar.getTime(); calendar.set(2007, 3, 12); Date end = calendar.getTime(); Task task1 = new Task("要件定義", start, end); series.add(task1); calendar.set(2007, 3, 12); Date start = calendar.getTime(); calendar.set(2007, 3, 24); Date end = calendar.getTime(); Task task2 = new Task("設計", start, end); series.add(task2); /* タスクの数だけ繰り返す */ data.add(series);では簡単なサンプルを作成して試してみます。 サンプルプログラム下記のサンプルを実行してみよう。/** * ガントチャートのデータ(TaskSeriesCollectionクラス) */ import org.jfree.chart.JFreeChart; import org.jfree.chart.ChartFactory; import org.jfree.data.gantt.TaskSeriesCollection; import org.jfree.data.gantt.TaskSeries; import org.jfree.data.gantt.Task; import java.util.Date; import java.util.Calendar; import javax.swing.JFrame; import java.awt.BorderLayout; import org.jfree.chart.ChartPanel; public class Test2_1 extends JFrame{ public static void main(String[] args) { Test2_1 frame = new Test2_1(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setBounds(10, 10, 500, 500); frame.setTitle("グラフサンプル"); frame.setVisible(true); } Test2_1(){ JFreeChart chart = ChartFactory.createGanttChart("プロジェクト管理", "項目", "日程", createData(), true, false, false); ChartPanel cpanel = new ChartPanel(chart); getContentPane().add(cpanel, BorderLayout.CENTER); } private TaskSeriesCollection createData(){ TaskSeriesCollection data = new TaskSeriesCollection(); TaskSeries series = new TaskSeries("計画"); Task task1 = new Task("要件定義", createData(2007, 3, 4), createData(2007, 3, 12)); Task task2 = new Task("設計", createData(2007, 3, 12), createData(2007, 3, 25)); Task task3 = new Task("開発", createData(2007, 4, 2), createData(2007, 4, 30)); Task task4 = new Task("テスト", createData(2007, 5, 1), createData(2007, 5, 10)); series.add(task1); series.add(task2); series.add(task3); series.add(task4); data.add(series); return data; } private Date createData(int year, int month, int date){ Calendar calendar = Calendar.getInstance(); calendar.set(year, month - 1, date); return calendar.getTime(); } }上記をコンパイルした後で実行すると次のように表示されます。 ![]() |
ガントチャートの場合は複数の系列のデータを取り扱う事が可能です。 ここでは例として次のようなデータを元にグラフを作成します。 系列:計画
系列:実績
系列を表すTaskSeriesクラスのオブジェクトを作成し、それぞれの系列にデータを登録していきます。 実際には次のように記述します。 TaskSeriesCollection data = new TaskSeriesCollection(); String[] taskname = {"要件定義", "設計", "開発", "テスト"}; TaskSeries series1 = new TaskSeries("計画"); TaskSeries series2 = new TaskSeries("実績"); Calendar calendar = Calendar.getInstance(); calendar.set(2007, 3, 4); Date start = calendar.getTime(); calendar.set(2007, 3, 12); Date end = calendar.getTime(); Task task11 = new Task("要件定義", start, end); series1.add(task11); /* タスクの数だけ繰り返す */ calendar.set(2007, 3, 4); Date start = calendar.getTime(); calendar.set(2007, 3, 14); Date end = calendar.getTime(); Task task21 = new Task("設計", start, end); series2.add(task21); /* タスクの数だけ繰り返す */ data.add(series1); data.add(series2);では簡単なサンプルを作成して試してみます。 サンプルプログラム下記のサンプルを実行してみよう。/** * 複数の系列のデータ */ import org.jfree.chart.JFreeChart; import org.jfree.chart.ChartFactory; import org.jfree.data.gantt.TaskSeriesCollection; import org.jfree.data.gantt.TaskSeries; import org.jfree.data.gantt.Task; import java.util.Date; import java.util.Calendar; import javax.swing.JFrame; import java.awt.BorderLayout; import org.jfree.chart.ChartPanel; public class Test3_1 extends JFrame{ public static void main(String[] args) { Test3_1 frame = new Test3_1(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setBounds(10, 10, 500, 500); frame.setTitle("グラフサンプル"); frame.setVisible(true); } Test3_1(){ JFreeChart chart = ChartFactory.createGanttChart("プロジェクト管理", "項目", "日程", createData(), true, false, false); ChartPanel cpanel = new ChartPanel(chart); getContentPane().add(cpanel, BorderLayout.CENTER); } private TaskSeriesCollection createData(){ TaskSeriesCollection data = new TaskSeriesCollection(); String[] taskname = {"要件定義", "設計", "開発", "テスト"}; TaskSeries series1 = new TaskSeries("計画"); TaskSeries series2 = new TaskSeries("実績"); Task task11 = new Task(taskname[0], createData(2007, 3, 4), createData(2007, 3, 12)); Task task12 = new Task(taskname[1], createData(2007, 3, 12), createData(2007, 3, 25)); Task task13 = new Task(taskname[2], createData(2007, 4, 2), createData(2007, 4, 30)); Task task14 = new Task(taskname[3], createData(2007, 5, 1), createData(2007, 5, 10)); series1.add(task11); series1.add(task12); series1.add(task13); series1.add(task14); Task task21 = new Task(taskname[0], createData(2007, 3, 4), createData(2007, 3, 14)); Task task22 = new Task(taskname[1], createData(2007, 3, 14), createData(2007, 4, 3)); Task task23 = new Task(taskname[2], createData(2007, 4, 5), createData(2007, 5, 10)); Task task24 = new Task(taskname[3], createData(2007, 5, 11), createData(2007, 5, 18)); series2.add(task21); series2.add(task22); series2.add(task23); series2.add(task24); data.add(series1); data.add(series2); return data; } private Date createData(int year, int month, int date){ Calendar calendar = Calendar.getInstance(); calendar.set(year, month - 1, date); return calendar.getTime(); } }上記をコンパイルした後で実行すると次のように表示されます。 ![]() |
グラフの描画領域を取得し、描画領域に対する設定を行っていきます。ファクトリメソッドを使ってJFreeChartクラスのオブジェクトを作成した場合は、JFreeChartクラスで用意されている「getPlot」メソッドを使ってPlotクラスのオブジェクトを取得します。 ガントチャートの場合には、取得したPlotクラスのオブジェクトを、PlotクラスのサブクラスであるCategoryPlotクラスにキャストして取得して使います。棒グラフの場合と同じですので、詳しくは「棒グラフの描画領域(CategoryPlotクラス)」を参照して下さい。 例えば次のように記述します。 JFreeChart chart = ChartFactory.createGanttChart(...); /* 引数は省略 */ CategoryPlot plot = (CategoryPlot)chart.getPlot();または次のように記述しても結構です。 JFreeChart chart = ChartFactory.createGanttChart(...); /* 引数は省略 */ CategoryPlot plot = chart.getCategoryPlot();では簡単なサンプルを作成して試してみます。 サンプルプログラム下記のサンプルを実行してみよう。/** * ガントチャートの描画領域(CategoryPlotクラス) */ import org.jfree.chart.JFreeChart; import org.jfree.chart.ChartFactory; import org.jfree.data.gantt.TaskSeriesCollection; import org.jfree.data.gantt.TaskSeries; import org.jfree.data.gantt.Task; import java.util.Date; import java.util.Calendar; import javax.swing.JFrame; import java.awt.BorderLayout; import org.jfree.chart.ChartPanel; import org.jfree.chart.plot.CategoryPlot; import java.awt.Color; public class Test4_1 extends JFrame{ public static void main(String[] args) { Test4_1 frame = new Test4_1(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setBounds(10, 10, 500, 500); frame.setTitle("グラフサンプル"); frame.setVisible(true); } Test4_1(){ JFreeChart chart = ChartFactory.createGanttChart("プロジェクト管理", "項目", "日程", createData(), true, false, false); CategoryPlot plot = chart.getCategoryPlot(); plot.setBackgroundPaint(Color.ORANGE); ChartPanel cpanel = new ChartPanel(chart); getContentPane().add(cpanel, BorderLayout.CENTER); } private TaskSeriesCollection createData(){ TaskSeriesCollection data = new TaskSeriesCollection(); String[] taskname = {"要件定義", "設計", "開発", "テスト"}; TaskSeries series1 = new TaskSeries("計画"); TaskSeries series2 = new TaskSeries("実績"); Task task11 = new Task(taskname[0], createData(2007, 3, 4), createData(2007, 3, 12)); Task task12 = new Task(taskname[1], createData(2007, 3, 12), createData(2007, 3, 25)); Task task13 = new Task(taskname[2], createData(2007, 4, 2), createData(2007, 4, 30)); Task task14 = new Task(taskname[3], createData(2007, 5, 1), createData(2007, 5, 10)); series1.add(task11); series1.add(task12); series1.add(task13); series1.add(task14); Task task21 = new Task(taskname[0], createData(2007, 3, 4), createData(2007, 3, 14)); Task task22 = new Task(taskname[1], createData(2007, 3, 14), createData(2007, 4, 3)); Task task23 = new Task(taskname[2], createData(2007, 4, 5), createData(2007, 5, 10)); Task task24 = new Task(taskname[3], createData(2007, 5, 11), createData(2007, 5, 18)); series2.add(task21); series2.add(task22); series2.add(task23); series2.add(task24); data.add(series1); data.add(series2); return data; } private Date createData(int year, int month, int date){ Calendar calendar = Calendar.getInstance(); calendar.set(year, month - 1, date); return calendar.getTime(); } }上記をコンパイルした後で実行すると次のように表示されます。 ![]() 今回は例として描画領域の背景色をオレンジに変更しました。また上記のオレンジの箇所がグラフの描画領域となります。 |
|