jfreechart & itext for adding many number of barch

2019-06-08 16:17发布

问题:

hello can any one help me in adding many number of bar charts to a single pdf. i have a code taken from d website to create a bar chart and save it in pdf. but couldn't save multiple bar charts to a single pdf.

import com.itextpdf.awt.DefaultFontMapper;
import com.itextpdf.text.Document;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfTemplate; 
import com.itextpdf.text.pdf.PdfWriter;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;
import java.io.FileOutputStream;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.data.general.DefaultPieDataset;

public class PieChartDemo {
public static void main(String[] args) {

    writeChartToPDF(generateBarChart(), 500, 400, "F:\\pdf\\bar.pdf");
    //TODO: Add code to generate PDFs with charts
}  



public static JFreeChart generateBarChart() {
    DefaultCategoryDataset dataSet = new DefaultCategoryDataset();
    dataSet.setValue(791, "Population", "1750 AD");
    dataSet.setValue(978, "Population", "1800 AD");
    dataSet.setValue(1262, "Population", "1850 AD");
    dataSet.setValue(1650, "Population", "1900 AD");
    dataSet.setValue(2519, "Population", "1950 AD");
    dataSet.setValue(6070, "Population", "2000 AD");


    JFreeChart chart = ChartFactory.createBarChart(
            "World Population growth", "Year", "Population in millions",
            dataSet, PlotOrientation.VERTICAL, false, true, false);

    return chart;
}
public static void writeChartToPDF(JFreeChart chart, int width, int height, String fileName) {
PdfWriter writer = null;

Document document = new Document();

try {
    writer = PdfWriter.getInstance(document, new FileOutputStream(
            fileName));
    document.open();
    PdfContentByte contentByte = writer.getDirectContent();
    PdfTemplate template = contentByte.createTemplate(width, height);
    Graphics2D graphics2d = template.createGraphics(width, height,
            new DefaultFontMapper());
    Rectangle2D rectangle2d = new Rectangle2D.Double(0, 0, width,
            height);
    for(int i=0;i<3;i++){
    chart.draw(graphics2d, rectangle2d);
}

    graphics2d.dispose();
    contentByte.addTemplate(template, 0, 0);

} catch (Exception e) {
    e.printStackTrace();
}
document.close();
}
}

回答1:

You are already doing the right thing except for the loop (I don't understand why you're drawing the same chart three times).

Please take a look at the DirectorCharts example on the official iText web site. On the director_charts.pdf, you can see two different charts each taking half of the space of a page.

PdfContentByte cb = writer.getDirectContent();
// define a width and a height
// in this case, I took the total width of the page
// and half the height of the page
float width = PageSize.A4.getWidth();
float height = PageSize.A4.getHeight() / 2;
// Create a Form XObject for a Pie chart
// You already have this part in your own code
PdfTemplate pie = cb.createTemplate(width, height);
Graphics2D g2d1 = new PdfGraphics2D(pie, width, height);
Rectangle2D r2d1 = new Rectangle2D.Double(0, 0, width, height);
getPieChart().draw(g2d1, r2d1);
g2d1.dispose();
cb.addTemplate(pie, 0, height);
// Create a Form XObject for a Bar chart
PdfTemplate bar = cb.createTemplate(width, height);
Graphics2D g2d2 = new PdfGraphics2D(bar, width, height);
Rectangle2D r2d2 = new Rectangle2D.Double(0, 0, width, height);
getBarChart().draw(g2d2, r2d2);
g2d2.dispose();
cb.addTemplate(bar, 0, 0);

The getPieChart() and getBarChart() method both create a JFreeChart object.

As you can see, you always have to create a PdfTemplate object (aka Form XObject) with a specific dimension and draw the chart onto that PdfTemplate. From that moment on, you can position the PdfTemplate on a page. If you want to switch to a new page, do:

document.newPage();

Also: if you don't want to use absolute coordinates to add the chart, you can wrap a PdfTemplate inside an Image. Replace the cb.addTemplate() methods with:

Image img = Image.getInstance(pie);
document.add(img);
img = Image.getInstance(bar);
document.add(img);

This could be even easier than the code snippet above: you create different PdfTemplate object with different charts, wrap them inside an Image and add them to the document. Important: you'll have to use smaller rectangles if you want to wrap the charts inside an Image, because otherwise, you won't be able to fit the charts on a single page (due to the default margins).

If you want to add the same barchart more than once, it goes without saying that you can either repeat the addTemplate() method with the same template and different coordinates more than once. If you wrap the template inside an Image object, you can add the same image to the document more than once.