Search code examples
javajfreechart

Jfreechart.draw() throws a Nullpointerexception


Issue: chart.draw((Graphics2D) emffile.create(), new Rectangle(1500, 600)) throws a Nullpointerexception.

The bar chart can be generated. Please help to look into the issue.

Here my code:

CategoryDataset dataset = createDataset();
JFreeChart chart = createChart(dataset);

emffile = new EMFGraphics2D(
        new File("C:\\Workspace\\eclipse\\MSReoprt\\chart.emf"),
        new Dimension(1500, 600)
);
emffile.setDeviceIndependent(true);

emffile.setRenderingHint(
    RenderingHints.KEY_RENDERING, 
    RenderingHints.VALUE_RENDER_QUALITY
);
emffile.setRenderingHint(
    RenderingHints.KEY_STROKE_CONTROL,
    RenderingHints.VALUE_STROKE_NORMALIZE
);
emffile.startExport();
chart.draw((Graphics2D) emffile.create(), new Rectangle(1500, 600));
emffile.endExport();
emffile.closeStream();

Category and jfreechart method:

private CategoryDataset createDataset()
{
    String series = "Availability";

    String category1 = "Portal";
    String category2 = "DB";

    DefaultCategoryDataset dataset = new DefaultCategoryDataset();
    dataset.addValue(100, series, category1);
    dataset.addValue(90, series, category2);
    return dataset;
}

public JFreeChart createChart(CategoryDataset dataset)
{
    FreeChart chart = ChartFactory.createBarChart
    (
        "Bar Chart Demo", //chart title
        "Category", //domain axis label
        "", //range axis label
        dataset, //data
        PlotOrientation.VERTICAL, //orientation
        true, //include legend
        true, //tooltips?
        false //URLs?
    );

    //set the background color for the chart...
    chart.setBackgroundPaint(Color.white);

    //get a reference to the plot for further customisation...
    CategoryPlot plot = chart.getCategoryPlot();
    plot.setBackgroundPaint(Color.white);
    plot.setDomainGridlinePaint(Color.white);
    plot.setRangeGridlinePaint(Color.gray);

    //set the range axis to display integers only...
    NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
    rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());

    //disable bar outlines...
    BarRenderer renderer = (BarRenderer) plot.getRenderer();
    renderer.setDrawBarOutline(false);
    renderer.setMaximumBarWidth(0.5);
    renderer.setItemMargin(4);

    //set up gradient paints for series...
    GradientPaint gp0 = new GradientPaint(
      0.0f, 0.0f, Color.blue,
      0.0f, 0.0f, Color.MAGENTA
    );
    //GradientPaint gp1 = new GradientPaint(0.0f, 0.0f, Color.green,
    //0.0f, 0.0f, Color.lightGray);
    //GradientPaint gp2 = new GradientPaint(0.0f, 0.0f, Color.red,
    //0.0f, 0.0f, Color.lightGray);
    renderer.setSeriesPaint(0, gp0);
    //renderer.setSeriesPaint(1, gp1);
    //renderer.setSeriesPaint(2, gp2);

    CategoryAxis domainAxis = plot.getDomainAxis();
    domainAxis.setCategoryLabelPositions(
        CategoryLabelPositions.createUpRotationLabelPositions(Math.PI / 6.0)
    );
    return chart;
}

Add stack trace:

Exception in thread "main" java.lang.NullPointerException
at org.freehep.graphicsio.emf.EMFGraphics2D.writePen(EMFGraphics2D.java:679)
at org.freehep.graphicsio.emf.EMFGraphics2D.writeStroke(EMFGraphics2D.java:575)
at org.freehep.graphicsio.AbstractVectorGraphicsIO.setStroke(AbstractVectorGraphicsIO.java:981)
at org.jfree.chart.plot.Plot.drawOutline(Plot.java:1125)
at org.jfree.chart.renderer.category.AbstractCategoryItemRenderer.drawOutline(AbstractCategoryItemRenderer.java:717)
at org.jfree.chart.plot.CategoryPlot.draw(CategoryPlot.java:3684)
at org.jfree.chart.JFreeChart.draw(JFreeChart.java:1229)
at org.jfree.chart.JFreeChart.draw(JFreeChart.java:1112)
at chart.BarChartDemo.export(BarChartDemo.java:61)
at chart.BarChartDemo.test(BarChartDemo.java:39)
at chart.BarChartDemo.main(BarChartDemo.java:137)

Solution

  • I posted this answer in the JFreeChart forum:

    This looks to me like a bug in the EMFGraphics2D class. The null pointer exception is happening at line 679:

    678    private void writePen(BasicStroke stroke, Color color) throws IOException {
    679        if (color.equals(penColor) && stroke.equals(getStroke()))
    

    I didn't run the code, but presumably either 'color' or 'stroke' is null. Since the code arrives here from line 575, it seems that 'color' is the null item (because 'stroke' isn't null, as it passed the instance of test):

    573    public void writeStroke(Stroke stroke) throws IOException {
    574        if (stroke instanceof BasicStroke) {
    575            writePen((BasicStroke) stroke, getColor());[/code]
    

    Now in all the Graphics2D implementations I've seen, getColor() never returns null (I've written test cases to explore this behaviour). But inspecting the EMFGraphics2D code, it seems as though this is the default plus any call to setPaint() with a non-Color argument will reset the colour to null. I think that is wrong.