Stacked Bar Charts in JRuby using JFreeChart

I was getting some comments on a previous post asking about building stacked bar charts in JRuby using JFreeChart, so here’s another example:

# Mostly inspired by 
# http://left.subtree.org/2007/01/15/creating-sparklines-with-jfreechart/
# have JFreeChart in your classpath, obviously, as well as jcommon.jar
require 'java'

module Graph
  class StackedBar
    include_class 'java.io.File'
    include_class 'org.jfree.chart.ChartUtilities'
    include_class 'org.jfree.chart.JFreeChart'
    include_class 'org.jfree.data.category.DefaultCategoryDataset'
    include_class 'org.jfree.chart.ChartFactory'
    include_class 'org.jfree.chart.plot.PlotOrientation'

    def initialize(width=600, height=400, data=[])
      @width = width
      @height = height
      dataset = create_sample_data() if data.empty?
      @chart = create_chart(dataset)
    end

    def render_to_file(filename, format="png")
      puts "Rendering graph to #{filename}"
      javafile = java.io.File.new(filename)
      ChartUtilities.saveChartAsPNG(javafile, @chart, @width, @height)
    end

    private
    def create_sample_data
      dataset = DefaultCategoryDataset.new
      dataset.addValue(1, "Submitted", "A")
      dataset.addValue(1, "Assigned", "A")
      dataset.addValue(3, "In-work", "A")
      dataset.addValue(1, "InVerfication", "A")
      dataset.addValue(2, "Delivered", "A")
      dataset.addValue(2, "Submitted", "B")
      dataset.addValue(1, "Rejected", "B")
      dataset.addValue(1, "Closed", "B")
      dataset.addValue(1, "Submitted", "C")
      dataset.addValue(1, "Assigned", "C")
      dataset.addValue(3, "In-work", "C")
      dataset.addValue(2, "On-hold", "C")

      return dataset
    end

    def create_chart(dataset)
      chart = ChartFactory.createStackedBarChart("XYZ's Development Projects",
                                                 "Project Name", 
                                                 "Hours", 
                                                 dataset,
                                                 PlotOrientation::VERTICAL, 
                                                 true, 
                                                 true, 
                                                 false)
      return chart    
    end
  end # class StackedBar  
end # class Graph

sb = Graph::StackedBar.new
sb.render_to_file("stacked_bar.png")

Here’s the output:

Stacked Bar chart example

Code here: http://kfahlgren.com/code/stacked_bar.jrb

One Response to “Stacked Bar Charts in JRuby using JFreeChart”

  1. enebo says:

    I updated your blog entry code snippet to use the new more endorsed
    Java integration methods:
    1. Include Java
    2. Import instead of include_class

    In addition, I decided to play with the addValue method and see what I
    could come up with besides raw arrays (which is actually probably the
    best way of loading raw datasets) if you were handcoding a graph.

    I would be fun if we could get some threads going on list to discuss
    good rubification of Java API techniques…

    -Tom

    —– jfree.rb —-
    include Java

    import org.jfree.data.category.DefaultCategoryDataset

    class DefaultCategoryDataset
    class Inner
    def initialize(dataset, row)
    @dataset, @row = dataset, row.to_s
    end

    # a value of nil can call ‘removeValue’
    def []=(column, value)
    @dataset.addValue value, @row, column.to_s
    end

    def populate(hash)
    hash.each_with_pair do |column, value|
    @dataset.addValue value, @row, column.to_s
    end
    end
    end

    def [](row)
    Inner.new self, row
    end
    end

    module Graph
    class StackedBar
    import org.jfree.chart.ChartUtilities
    import org.jfree.chart.JFreeChart
    import org.jfree.chart.ChartFactory
    import org.jfree.chart.plot.PlotOrientation

    def initialize(width=600, height=400, dataset=create_sample_data)
    @height, @width, @chart = height, width, create_chart(dataset)
    end

    def render_to_file(filename, format=”png”)
    puts “Rendering graph to #{filename}”
    javafile = java.io.File.new(filename)
    ChartUtilities.saveChartAsPNG(javafile, @chart, @width, @height)
    end

    private
    def create_sample_data
    # I thought about method_missing for dataset.submitted but since these
    # can be arbitrary strings with method-name unfriendly chars in it I
    # decided against it.

    # This also allows symbols as well as strings
    dataset = DefaultCategoryDataset.new
    dataset[:Submitted].populate(:A => 1, :B => 2, :C => 3)
    dataset[:Assigned].populate(:A => 1, :C => 1)
    dataset["In-work"].populate(:A => 3, :C => 3)
    dataset[:InVerfication][:A] = 1
    dataset[:Delivered][:A] = 2
    dataset[:Rejected][:B] = 1
    dataset[:Closed][:B] = 1
    dataset["On-hold"][:C] = 2
    dataset
    end

    def create_chart(dataset)
    ChartFactory.createStackedBarChart(“XYZ’s Development Projects”,
    “Project Name”,
    “Hours”,
    dataset,
    PlotOrientation::VERTICAL,
    true,
    true,
    false)
    end
    end # class StackedBar
    end # class Graph

    sb = Graph::StackedBar.new
    sb.render_to_file(“stacked_bar.png”)