2011-03-13 91 views
7

我有一個具有抽象方法draw(Graphics2D g2)和方法print(),showPreview(),printPDF()的抽象類。對於我的Java程序中的每個文檔,我實現了draw(),因此我可以打印,顯示預覽併爲每個文檔創建一個PDF文件。 我的問題是如何使用該Graphics對象的多個頁面創建一個PDF。 我通過爲每個頁面創建PDF文件來解決此問題,然後將這些文件合併到一個新文件中。但是一定有更好的辦法。 我有以下的代碼與一個網頁創建PDF:如何使用Java和itext從Graphics對象創建多個頁面的PDF

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()); 
    } 
} 

回答

9
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中可能更高效。

將您的整個界面渲染成一個巨大的PdfTemplate(使用g2d),一次。然後將該模板繪製到所有頁面中,以便在當前頁面的頁邊空白處顯示您想要的部分(「媒體框」)。

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做了相當多的魔術來隱藏你的差異,但我們仍然需要在這裏處理一下......因此,在邊界框和繪圖位置的負座標。

這就是「衛生巾背面」編碼,我完全有可能犯了一個錯誤或兩個錯誤......但這就是主意。

+0

非常感謝你,它適用於以下更改。 – Jan

+0

哪些變化? PS:這是你點擊正確答案旁邊的空白複選標記的部分,讓其他人知道誰是對的(並給予這個人某種聲望)。 「我」在這種情況下。此外,如果您提出多個問題並且從不標記他們回答,其他人將會看到您的可憐答案百分比,並且不太可能打擾,因爲他們知道即使他們是對的,他們也不會給予他們代表。 –

+0

對不起馬克,我嘗試瞭解這個網站是如何工作的。 我沒有意識到PdfContentByte可以被每個頁面重複使用。 我做了修改: PdfTemplate template = cb.createTemplate(_pageWidth,entireHeight); g2 = template.createGraphics(_pageWidth,entireHeight); (int curPg = 1; curPg <= _numberOfPages; ++ curPg){ ..... cb.addTemplate(hugeTempl,0,-_pageHeight *(_numberOfPages-curPg)); document.newPage(); } – Jan

0

我在遇到上述代碼時遇到了麻煩(某些方法在當前的itextpdf版本中似乎發生了變化)。這是我的解決方案:

import com.itextpdf.awt.PdfGraphics2D; 
import com.itextpdf.text.Document; 
import com.itextpdf.text.PageSize; 
import com.itextpdf.text.pdf.PdfContentByte; 
import com.itextpdf.text.pdf.PdfTemplate; 
import com.itextpdf.text.pdf.PdfWriter; 
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Graphics2D; 
import java.awt.event.WindowEvent; 
import java.io.FileOutputStream; 
import java.io.OutputStream; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import net.miginfocom.swing.MigLayout; 

public class PanelToPDF { 

    private static JFrame frame= new JFrame(); 
    private static JPanel view= new JPanel(); 
    private static float pageWidth= PageSize.A4.getWidth(); 
    private static float pageHeight= PageSize.A4.getHeight(); 

    public static void main(String[] args) throws Exception { 
     System.out.println("Page width = " + pageWidth + ", height = " + pageHeight); 

     initPane(); 
     createMultipagePDF(); 

     frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_CLOSING)); 
    } 


    private static void initPane() { 
     view.setLayout(new MigLayout()); 
     view.setBackground(Color.WHITE); 

     for (int i= 1; i <= 160; ++i) { 
      JLabel label= new JLabel("This is a test! " + i); 
      label.setForeground(Color.BLACK); 
      view.add(label, "wrap"); 

      JPanel subPanel= new JPanel(); 
      subPanel.setBackground(Color.RED); 
      view.add(subPanel); 
     } 

     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setSize(new Dimension(Math.round(pageWidth), Math.round(pageHeight))); 
     frame.add(view); 
     frame.setVisible(true); 
    } 

    private static void createMultipagePDF() throws Exception { 
     // Calculate the number of pages required. Use the preferred size to get 
     // the entire panel height, rather than the panel height within the JFrame 
     int numPages= (int) Math.ceil(view.getPreferredSize().height/pageHeight); // int divided by float 

     // Output to PDF 
     OutputStream os= new FileOutputStream("test.pdf"); 
     Document doc= new Document(); 
     PdfWriter writer= PdfWriter.getInstance(doc, os); 
     doc.open(); 
     PdfContentByte cb= writer.getDirectContent(); 

     // Iterate over pages here 
     for (int currentPage= 0; currentPage < numPages; ++currentPage) { 
      doc.newPage(); // not needed for page 1, needed for >1 

      PdfTemplate template= cb.createTemplate(pageWidth, pageHeight); 
      Graphics2D g2d= new PdfGraphics2D(template, pageWidth, pageHeight * (currentPage + 1)); 
      view.printAll(g2d); 
      g2d.dispose(); 

      cb.addTemplate(template, 0, 0); 
     } 

     doc.close(); 
    } 
相關問題