如何使用Java和itext从Graphics对象创建包含多个页面的PDF [英] How to create a PDF with multiple pages from a Graphics object with Java and itext

查看:132
本文介绍了如何使用Java和itext从Graphics对象创建包含多个页面的PDF的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个抽象类,抽象方法draw(Graphics2D g2),方法是print(),showPreview(),printPDF()。对于我的Java程序中的每个文档,我实现了draw(),因此我可以打印,显示预览并为每个文档创建PDF文件。
我的问题是如何使用该Graphics对象创建包含多个页面的PDF。
我通过为每个页面创建PDF文件来解决它,然后将文件合并到一个新文件中。但必须有更好的方法。
我有以下代码用一页创建PDF:

I have an abstract class with an abstract method draw(Graphics2D g2), and the methods print(), showPreview(), printPDF(). For each document in my Java program, I implement draw(), so I can print, show preview and create a PDF file for each document. My problem is how to create a PDF with multiple pages from that Graphics object. I solved it by creating a PDF file for each page, and then merge the files into one new file. But there must be a better way. I have following code to create PDF with one page:

public void printPDF1(){
    JFileChooser dialog = new JFileChooser();
    String filePath = "";
    int dialogResult = dialog.showSaveDialog(null);
    if (dialogResult==JFileChooser.APPROVE_OPTION){
        filePath = dialog.getSelectedFile().getPath();
    }
    else return;
    try {
        Document document = new Document(new Rectangle(_pageWidth, _pageHeight));
        PdfWriter writer = PdfWriter.getInstance(document,
                new FileOutputStream(filePath));
        document.open();

        PdfContentByte cb = writer.getDirectContent();
        g2 = cb.createGraphics(_pageWidth, _height);
        g2.translate(0, (_numberOfPages - _pageNumber) * _pageHeight);
        draw(g2);
        g2.dispose();
        document.close();
    } 
    catch (Exception e2) {
        System.out.println(e2.getMessage());
    }
}


推荐答案

    document.open();

    // the same contentByte is returned, it's just flushed & reset during
    // new page events.
    PdfContentByte cb = writer.getDirectContent();

    for (int _pageNumber = 0; _pageNumber < _numberofPages; ++_numberOfPages) {
      /*******************/
      //harmless in first pass, *necessary* in others
      document.newPage(); 
      /*******************/

      g2 = cb.createGraphics(_pageWidth, _height);
      g2.translate(0, (_numberOfPages - _pageNumber) * _pageHeight);
      draw(g2);
      g2.dispose();
    }

    document.close();

所以你要渲染整个界面N次,只显示一个页面大小的切片在不同的地方。这在印刷世界IIRC中被称为条带化。聪明,但它在PDF中可能更有效。

So you're rendering your entire interface N times, and only showing a page-sized slice of it in different locations. That's called "striping" in print-world IIRC. Clever, but it could be more efficient in PDF.

将整个界面渲染成一个巨大的PdfTemplate(带g2d),一次。然后将该模板绘制到所有页面中,使得您想要的部分在当前页面的边距内可见(媒体框)。

Render your entire interface into one huge PdfTemplate (with g2d), once. Then draw that template into all your pages such that the portion you want is visible inside the current page's margins ("media box").

PdfContentByte cb = writer.getDirectContent();
float entireHeight = _numberOfPages * _pageHeight;
PdfTemplate hugeTempl = cb.createTemplate( 0, -entireHeight, pageWidth, _pageHeight );
g2 = hugeTempl.createGraphics(0, -entireHeight, _pageWidth, _pageHeight ); 
draw(g2);
g2.dispose();

for (int curPg = 0; curPg < _numberOfPages; ++curPg) {
  cb.addTemplateSimple( hugeTempl, 0, -_pageHeight * curPg );

  document.newPage();
}

PDF的坐标空间在左下角设置0,0,这些值随着你向上和向右增加。 PdfGraphis2D做了相当多的魔法来隐藏与你的区别,但我们仍然需要在这里处理它...因此在边界框和绘图位置的负坐标。

PDF's coordinate space sets 0,0 in the lower left corner, and those values increase as you go up and to the right. PdfGraphis2D does a fair amount of magic to hide that difference from you, but we still have to deal with it a bit here... thus the negative coordinates in the bounding box and drawing locations.

这就是所有背面的餐巾纸编码,我完全有可能在那里犯了一两个错误......但这就是主意。

This is all "back of the napkin" coding, and it's entirely possible I've made a mistake or two in there... but that's the idea.

这篇关于如何使用Java和itext从Graphics对象创建包含多个页面的PDF的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆