Creating charts on Web pages with Java and GChart

125

Author: Ben Martin

The Apache-licensedGChart utility lets you quickly generate nice-looking charts on your Web site.

GChart is implemented with the Google Web Toolkit (GWT), which we introduced recently. To install GChart, just extract the distribution zip file. You can work with GChart in your own GWT applications by using it in Eclipse. You first have to tell Eclipse where to find the extracted gchart.jar file and modify your GWT module file to include GChart. These last two setups are described in detail in GChart’s installation instructions. Note that you will most likely need to install x86 packages on an x86_64 Linux distribution because GWT does not currently have a 64-bit download. To get GWT working from Eclipse on a Fedora 8 x86_64 installation I had to download and install the 32-bit version of Sun’s JDK. Once the JDK is installed, right-click your project in Eclipse, open the Properties window, select the Java Build Path entry in the list on the left side of the dialog, and then the Libraries tab on the right side. Change your JRE system library from there to the 32-bit Sun JDK.

To use GWT, you code in Java. The final build produces JavaScript which runs on the client machine. To add a GChart to your Web site, create a subclass of the Java class com.googlecode.gchart.client.GChart and use calls to set the title, size of the chart, data points, and axis labels. As you are using GWT, your site will have a subclass of the EntryPoint class. Your EntryPoint subclass will have a onModuleLoad method which is used to set up the Web page, normally using RootPanel.get().add() to include elements on the page. Assuming that your GChart subclass is called VerySimpleChart, the chart is then put onto your Web page using something like RootPanel.get().add(new VerySimpleChart());.

A common way of putting charts onto a Web site is to generate images on the server, which are then sent to Web browsers. You can implement a similar design with GChart by using Remote Method Invocation (RMI) to call a servlet from a browser to obtain new data and update the graph. Given that GChart works on the client side already and the data itself is likely to be fairly small, you might like to send the data for four or five different graphs with the original Web page load. Then you can update a graph to show any of these data sets without needing any interaction with the Web server.

An example where you might like to allow the user to dynamically change the chart, suppose that you are showing exchange rates. You might want to let the user switch between seeing today, the last five days, or the last month, quarter, or year. As an example I’ll just allow switching between the last five days and last month. Properly handling a time axis can be tricky with graphs because you need to make sure that axis labels are readable and convey logical time intervals. For example, if you are showing the last five days, you would not like the axis labels to include hours just because your data set happens to include a point that is at 3 a.m.

The first thing to do is to define a class that will contain your point data. I’ll address the sticky issue of axis labeling by making each point include a suitable axis label. This is acceptable because there are only a handful of points in the example and they are uniformly distributed along the time axis. I use the ChartType to contain three values and also a visit method that can be invoked to place this point on a GChart. The ChartTuple class and all of the below methods are in the VerySimpleChart class unless otherwise stated.

public class ChartTuple { double m_x; double m_y; String m_xLabel; ChartTuple( double x, double y, String xLabel ) { m_x = x; m_y = y; m_xLabel = xLabel; } void visit( Curve c ) { c.addPoint( m_x, m_y ); getXAxis().addTick( m_x, m_xLabel ); } };

In a real application the data would likely be loaded from an XML file, relational database, or JavaScript Object Notation (JSON) declaration. In the example I’ll just initialize the values directly from Java. Each of the methods shown will return a collection of ChartTuples that represent a given time interval.

public java.util.List getLastFiveDaysChartData() { java.util.List ret = new java.util.ArrayList(); ret.add( new ChartTuple( 1, 4, "Web 9" ) ); ret.add( new ChartTuple( 2, 6, "Thur 10" ) ); ret.add( new ChartTuple( 3, 3, "Fri 11" ) ); ret.add( new ChartTuple( 4, 4, "Sat 12" ) ); ret.add( new ChartTuple( 5, 4, "Sun 13" ) ); return ret; } public java.util.List getLastMonthChartData() { java.util.List ret = new java.util.ArrayList(); ret.add( new ChartTuple( 1, 12, "1st" ) ); ret.add( new ChartTuple( 2, 24, "8th" ) ); ret.add( new ChartTuple( 3, 6, "15th" ) ); ret.add( new ChartTuple( 4, 31, "22nd" ) ); ret.add( new ChartTuple( 5, 3, "29th" ) ); return ret; }

I create the graph itself in a loadData method. Because we want to handle different time intervals, the x-axis label is a parameter of the loadData method. First I clear any existing graph and update the GChart with the new dataset. Most of the methods called in loadData are from GChart, which is a superclass of my GChart object. You could call a similar method to loadData with a data set acquired through AJAX from a servlet using a GWT remote procedure call.

public void loadData( java.util.List d, String xLabel ) { clearCurves(); addCurve(); getXAxis().setTickCount( d.size() ); for (java.util.Iterator i = d.iterator(); i.hasNext(); ) { ChartTuple t = (ChartTuple) i.next(); t.visit(getCurve()); } getCurve().setLegendLabel("joy"); getXAxis().setAxisLabel(xLabel); getYAxis().setAxisLabel("y"); getXAxis().setHasGridlines( true ); getCurve().getSymbol().setSymbolType(SymbolType.BOX_CENTER); getCurve().getSymbol().setWidth(5); getCurve().getSymbol().setHeight(5); getCurve().getSymbol().setBorderWidth(0); getCurve().getSymbol().setBackgroundColor("navy"); getCurve().getSymbol().setFillThickness(2); getCurve().getSymbol().setFillSpacing(5); update(); }

The constructor of my GChart subclass, VerySimpleChart, just sets up the GChart size and title and uses a default data set to call loadData with.

public VerySimpleChart() { setChartTitle("Dynamic date ranges example..."); setChartSize(550, 250); loadData( getLastFiveDaysChartData(), "day" ); }

I then switch to my EntryPoint subclass, mygchart. The GWT onModuleLoad method creates a few buttons and calls loadData with the appropriate dataset when the button is clicked.

public class mygchart implements EntryPoint { ... public void onModuleLoad() { final VerySimpleChart mychart = new VerySimpleChart(); RootPanel.get().add( mychart ); RootPanel.get().add( new Button("Month graph", new ClickListener() { public void onClick(Widget sender) { mychart.loadData( mychart.getLastMonthChartData(), "Month" ); } } )); RootPanel.get().add( new Button("5 Day graph", new ClickListener() { public void onClick(Widget sender) { mychart.loadData( mychart.getLastFiveDaysChartData(), "day" ); } } )); }

With these pieces of code in place you can click on a button on the Web page to change the GChart from showing the last five days data to showing the last month.

If you are already using GWT or plan to give it a whirl for an upcoming project, then GChart will let you make some nice charts with minimal fuss. The graph API offered by GChart also lets you customize how a graph will be presented, how many tick marks will be shown, what labels each tick will show, the colors and thickness of elements, and other things you would expect from a chart creation tool. You might like to also take a look at the GChart gallery for screenshots and example code.

Categories:

  • Programming
  • Java
  • Internet & WWW
  • Graphics & Multimedia