忍者ブログ

軽Lab

 Javaを中心とした、プログラミング関係のナレッジベース

Home > JavaFX入門 > JavaFX チャート

JavaFX チャート

円グラフや散布図といったグラフは、JavaFXにおいてチャート・パッケージとしてまとめられている。細かな出力設定をするにはクラス継承やCSS設定が必要だが、デフォルトの見た目で出力する分には簡単にデータ出力できる。

■ チャートの種類

JavaFXで用意されているチャートの一覧を以下に示す。『Stacked○○』というクラスは積上グラフを表している。

グラフ クラス 出力イメージ
円グラフ PieChart
折れ線グラフ LineChart
面グラフ AreaChart
StackedAreaChart
バブルチャート BubbleChart
散布図 ScatterChart
棒グラフ BarChart
StackedBarChart

また、上記のイメージはデフォルト出力であるが、チャートもシーングラフの一種であるため、スタイルシートやエフェクトの適用により見た目を変えることができる。イベントハンドラの登録なども行うことができるため、チャート上にマウスを載せた場合に追加の情報を出力することも可能である。

■ サンプルコード

以下に各チャートを利用するサンプルコードを示す。

■ サンプルコード

package application_fx;

import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Side;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.chart.AreaChart;
import javafx.scene.chart.BubbleChart;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.PieChart;
import javafx.scene.chart.ScatterChart;
import javafx.scene.chart.StackedBarChart;
import javafx.scene.chart.XYChart;
import javafx.scene.chart.XYChart.Series;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class TestChart extends Application
{
    public static void main(String[] args)
    {
        launch( args );
    }

    @Override
    public void start(Stage primaryStage) throws Exception
    {
        // フォント色がおかしくなることへの対処
        System.setProperty( "prism.lcdtext" , "false" );
        
        // シーングラフの作成
        HBox        root    = new HBox();
        VBox        left    = new VBox( 2.0 );
        VBox        right    = new VBox( 2.0 );
        root.getChildren().addAll( left , right );
        
        // チャートを作成
        left.getChildren().add( createPieChart() );             // 円グラフの追加
        left.getChildren().add( createLineChart() );            // 折れ線グラフの追加
        left.getChildren().add( createAreaChart() );            // 面グラフの追加
        right.getChildren().add( createBubbleChart() );         // バブルチャートの追加
        right.getChildren().add( createScatterChart() );        // 散布図の追加
        right.getChildren().add( createBarChart() );            // 棒グラフの追加
        
        // シーンの作成
        Scene       scene   = new Scene( root , 1000 , 900 );
        
        // ウィンドウ表示
        primaryStage.setScene( scene );
        primaryStage.show();
        
    }
    
    /**
     * 円グラフを作成
     * 『国内Webブラウザシェア(2015年8月)』
     * 元データ(https://webrage.jp/mobile/data/pc_browser_share.html)
     * @return
     */
    public Node createPieChart()
    {
        // 円グラフを作成
        PieChart    chart   = new PieChart();
        
        // グラフにデータを追加
        ObservableList<PieChart.Data> data = 
            FXCollections.observableArrayList(
                    new PieChart.Data( "IE ( 41.09 )" , 41.09 ),
                    new PieChart.Data( "Chrome ( 31.76 )" , 31.76 ),
                    new PieChart.Data( "Firefox ( 12.52 )" , 12.52 ),
                    new PieChart.Data( "Safari ( 2.52 )" , 2.52 ),
                    new PieChart.Data( "other ( 12.11 )" , 12.11 )
                    );
        chart.setData( data );
        chart.setMinWidth( 500 );
        
        // グラフの角度変更
        chart.setStartAngle( 90 );
        
        // タイトルを設定
        chart.setTitle( "国内Webブラウザシェア(2015年8月)" );
        chart.setLegendSide( Side.LEFT );
        
        return chart;
    }
    
    /**
     * 折れ線グラフを作成
     * 『各国のGDP』
     * 元データ(http://www.stat.go.jp/data/sekai/0116.htm)
     * @return
     */
    @SuppressWarnings("unchecked")
    public Node createLineChart()
    {
        // 折れ線グラフ
        CategoryAxis                xAxis   = new CategoryAxis();
        NumberAxis                  yAxis   = new NumberAxis();
        LineChart<String, Number>   chart   = new LineChart<String, Number>( xAxis , yAxis );
        chart.setMaxWidth( 500 );
        
        // データを作成
        Series< String , Number > series1    = new Series<String, Number>();
        series1.setName( "日本" );
        series1.getData().add( new XYChart.Data<String, Number>( "2000年" , 4730102 ) );
        series1.getData().add( new XYChart.Data<String, Number>( "2005年" , 4578144 ) );
        series1.getData().add( new XYChart.Data<String, Number>( "2010年" , 5510722 ) );
        series1.getData().add( new XYChart.Data<String, Number>( "2012年" , 5952575 ) );
        series1.getData().add( new XYChart.Data<String, Number>( "2013年" , 4920680 ) );

        Series< String , Number > series2    = new Series<String, Number>();
        series2.setName( "アメリカ" );
        series2.getData().add( new XYChart.Data<String, Number>( "2000年" , 10284800 ) );
        series2.getData().add( new XYChart.Data<String, Number>( "2005年" , 13093700 ) );
        series2.getData().add( new XYChart.Data<String, Number>( "2010年" , 14964400 ) );
        series2.getData().add( new XYChart.Data<String, Number>( "2012年" , 16163200 ) );
        series2.getData().add( new XYChart.Data<String, Number>( "2013年" , 16768100 ) );
        
        Series< String , Number > series3    = new Series<String, Number>();
        series3.setName( "中国" );
        series3.getData().add( new XYChart.Data<String, Number>( "2000年" , 1192836 ) );
        series3.getData().add( new XYChart.Data<String, Number>( "2005年" , 2287237 ) );
        series3.getData().add( new XYChart.Data<String, Number>( "2010年" , 5949785 ) );
        series3.getData().add( new XYChart.Data<String, Number>( "2012年" , 8229447 ) );
        series3.getData().add( new XYChart.Data<String, Number>( "2013年" , 9181204 ) );
        
        // データを登録
        chart.getData().addAll( series1 , series2 , series3 );
        
        // タイトルを設定
        chart.setTitle( "国内総生産(名目GDP,米ドル表示)" );
        
        return chart;
    }
    
    /**
     * 面グラフを作成
     * 『ウイルス届出件数の推移』
     * 元データ(https://www.ipa.go.jp/security/txt/2015/q2outline.html)
     * @return
     */
    @SuppressWarnings("unchecked")
    public Node createAreaChart()
    {
        // 面グラフ
        CategoryAxis                xAxis   = new CategoryAxis();
        NumberAxis                  yAxis   = new NumberAxis();
        AreaChart<String, Number>   chart   = new AreaChart<String, Number>( xAxis , yAxis );
        chart.setMaxWidth( 500 );

        // データを作成
        Series< String , Number > series1    = new Series<String, Number>();
        series1.setName("ウィルス届出件数");
        series1.getData().add( new XYChart.Data<String, Number>( "2014年\n4-6月" , 1292 ) );
        series1.getData().add( new XYChart.Data<String, Number>( "2014年\n7-9月" , 1298 ) );
        series1.getData().add( new XYChart.Data<String, Number>( "2014年\n10-12月" , 1010 ) );
        series1.getData().add( new XYChart.Data<String, Number>( "2015年\n1-3月" , 937 ) );
        series1.getData().add( new XYChart.Data<String, Number>( "2015年\n4-6月" , 772 ) );

        Series< String , Number > series2    = new Series<String, Number>();
        series2.setName("ウィルス被害件数");
        series2.getData().add( new XYChart.Data<String, Number>( "2014年\n4-6月" , 1 ) );
        series2.getData().add( new XYChart.Data<String, Number>( "2014年\n7-9月" , 0 ) );
        series2.getData().add( new XYChart.Data<String, Number>( "2014年\n10-12月" , 0 ) );
        series2.getData().add( new XYChart.Data<String, Number>( "2015年\n1-3月" , 0 ) );
        series2.getData().add( new XYChart.Data<String, Number>( "2015年\n4-6月" , 2 ) );

        // データを登録
        chart.getData().addAll( series1 , series2 );
        
        // タイトルを設定
        chart.setTitle( "ウイルス届出件数の推移" );
        
        return chart;
    }
    
    /**
     * バブルチャートを作成
     * 元データ:適当
     * @return
     */
    public Node createBubbleChart()
    {
        // x軸作成
        NumberAxis                  xAxis   = new NumberAxis();
        xAxis.setLabel( "直帰率" );
        xAxis.setAutoRanging( false );
        xAxis.setUpperBound( 100 );
        xAxis.setLowerBound(   0 );
        xAxis.setTickUnit( 20 );
        
        // y軸作成
        NumberAxis                  yAxis   = new NumberAxis();
        yAxis.setLabel( "新規訪問の割合" );
        yAxis.setAutoRanging( false );
        yAxis.setUpperBound( 100 );
        yAxis.setLowerBound(   0 );
        yAxis.setTickUnit( 20 );

        // バブルチャート作成
        BubbleChart<Number,Number>  chart   = new BubbleChart<Number,Number>( xAxis , yAxis );
        chart.setMaxWidth( 500 );

        // データを作成
        Series< Number , Number > series1    = new Series<Number, Number>();
        series1.setName("Webサイト訪問者数");
        series1.getData().add( new XYChart.Data<Number, Number>( 1  , 1  , 30 ) );
        series1.getData().add( new XYChart.Data<Number, Number>( 10 , 10 , 20 ) );
        series1.getData().add( new XYChart.Data<Number, Number>( 80 , 20 , 2.5 ) );
        series1.getData().add( new XYChart.Data<Number, Number>( 40 , 57 , 8) );
        series1.getData().add( new XYChart.Data<Number, Number>( 20 , 4  , 5 ) );
        series1.getData().add( new XYChart.Data<Number, Number>( 8  , 60 , 3 ) );
        series1.getData().add( new XYChart.Data<Number, Number>( 10 , 65 , 5 ) );

        // データを登録
        chart.getData().add( series1 );

        // タイトルを設定
        chart.setTitle( "Webサイト訪問傾向" );
        
        return chart;
    }
    
    /**
     * 散布図を作成
     * 『東京における毎月1日の平均気温と湿度(2014年11月~2015年10月)』
     * 元データ:(http://www.data.jma.go.jp/gmd/risk/obsdl/index.php)
     * @return
     */
    public Node createScatterChart()
    {
        // 散布図作成
        NumberAxis                  xAxis   = new NumberAxis();
        NumberAxis                  yAxis   = new NumberAxis();
        ScatterChart<Number,Number> chart   = new ScatterChart<Number,Number>( xAxis , yAxis );
        chart.setMaxWidth( 500 );
        
        // データを作成
        xAxis.setLabel( "気温" );
        yAxis.setLabel( "湿度" );
        Series< Number , Number > series1    = new Series<Number, Number>();
        series1.setName( "東京における平均気温と湿度" );
        series1.getData().add( new XYChart.Data<Number, Number>( 16.8 , 85 ) );
        series1.getData().add( new XYChart.Data<Number, Number>( 13.5 , 92 ) );
        series1.getData().add( new XYChart.Data<Number, Number>( 3.7  , 41 ) );
        series1.getData().add( new XYChart.Data<Number, Number>( 4    , 32 ) );
        series1.getData().add( new XYChart.Data<Number, Number>( 6.9  , 79 ) );
        series1.getData().add( new XYChart.Data<Number, Number>( 13.9 , 76 ) );
        series1.getData().add( new XYChart.Data<Number, Number>( 20.5 , 63 ) );
        series1.getData().add( new XYChart.Data<Number, Number>( 23.6 , 51 ) );
        series1.getData().add( new XYChart.Data<Number, Number>( 20.5 , 98 ) );
        series1.getData().add( new XYChart.Data<Number, Number>( 30.5 , 76 ) );
        series1.getData().add( new XYChart.Data<Number, Number>( 23.7 , 96 ) );
        series1.getData().add( new XYChart.Data<Number, Number>( 19.4 , 79 ) );
        
        // データを登録
        chart.getData().add( series1 );
        
        // タイトルを設定
        chart.setTitle( "東京における毎月1日の平均気温と湿度\n(2014年11月~2015年10月)" );
        
        return chart;
    }
    
    /**
     * 棒グラフを作成
     * 『貿易相手国上位4カ国の推移』
     * 元データ(http://www.customs.go.jp/toukei/suii/html/y3.pdf)
     * @return
     */
    @SuppressWarnings("unchecked")
    public Node createBarChart()
    {
        // 棒グラフを作成
        CategoryAxis                    xAxis   = new CategoryAxis();
        NumberAxis                      yAxis   = new NumberAxis();
        StackedBarChart<String,Number>  chart   = new StackedBarChart<String,Number>( xAxis , yAxis );
        chart.setMaxWidth( 500 );
        
        // データを作成
        Series< String , Number > series1    = new Series<String, Number>();
        series1.setName("アメリカ");
        series1.getData().add( new XYChart.Data<String, Number>( "1995" , 184094 ) );
        series1.getData().add( new XYChart.Data<String, Number>( "2000" , 231347 ) );
        series1.getData().add( new XYChart.Data<String, Number>( "2005" , 218797 ) );
        series1.getData().add( new XYChart.Data<String, Number>( "2010" , 162854 ) );
        series1.getData().add( new XYChart.Data<String, Number>( "2014" , 211919 ) );

        Series< String , Number > series2    = new Series<String, Number>();
        series2.setName("中国");
        series2.getData().add( new XYChart.Data<String, Number>( "1995" , 54428 ) );
        series2.getData().add( new XYChart.Data<String, Number>( "2000" , 92158 ) );
        series2.getData().add( new XYChart.Data<String, Number>( "2005" , 208123 ) );
        series2.getData().add( new XYChart.Data<String, Number>( "2010" , 264985 ) );
        series2.getData().add( new XYChart.Data<String, Number>( "2014" , 325579 ) );

        Series< String , Number > series3    = new Series<String, Number>();
        series3.setName("韓国");
        series3.getData().add( new XYChart.Data<String, Number>( "1995" , 45500 ) );
        series3.getData().add( new XYChart.Data<String, Number>( "2000" , 55135 ) );
        series3.getData().add( new XYChart.Data<String, Number>( "2005" , 78413 ) );
        series3.getData().add( new XYChart.Data<String, Number>( "2010" , 79642 ) );
        series3.getData().add( new XYChart.Data<String, Number>( "2014" , 89873 ) );

        Series< String , Number > series4    = new Series<String, Number>();
        series4.setName("台湾");
        series4.getData().add( new XYChart.Data<String, Number>( "1995" , 40566 ) );
        series4.getData().add( new XYChart.Data<String, Number>( "2000" , 58042 ) );
        series4.getData().add( new XYChart.Data<String, Number>( "2005" , 68034 ) );
        series4.getData().add( new XYChart.Data<String, Number>( "2010" , 66188 ) );
        series4.getData().add( new XYChart.Data<String, Number>( "2014" , 67992 ) );
        
        // データを登録
        chart.getData().addAll( series1 , series2 , series3 , series4 );
        
        // タイトルを設定
        chart.setTitle( "貿易相手国上位4カ国の推移(億円)" );
        
        return chart;
    }
        

}

■ 実行結果


■ 解説

プログラムの流れはstart関数にまとめられており、43行目~48行目で各チャートをシーングラフに追加している。チャート作成のプログラムについては、create○○Chart関数にまとめている。プログラムを読むときのポイントとして『円グラフ』と『円グラフ以外』で分けて考えるとよい。プログラムを組む上で、両者の違いは以下のとおりである。

◇ 円グラフの利用
データはFXCollections.observableArrayList型のリストとして渡す。デフォルトでは時計の3時の方向から円グラフが開始されるため、setStartAngle関数により開始位置を12時の方向に変えるとわかりやすい(83行目)

◇ 円グラフ以外の利用
円グラフ以外のグラフは、すべて2つの軸を設定する必要がある。軸の種類には文字列の軸『CategoryAxis』と数値の軸『NumberAxis』が存在する。データはSeries型のリストとして渡し、1つのチャート上に複数のデータを持たせることができる。

■ 参照

  1. JavaFX: JavaFX UIコンポーネントの操作
  2. JavaDoc - パッケージjavafx.scene.chartの階層
Home > JavaFX入門 > JavaFX チャート

- ランダム記事 -
- PR -

コメント

プロフィール

管理者:
 連絡はContactよりお願いします。

PR