2011-03-13 4 views
7

J'ai une classe abstraite avec une méthode abstraite draw (Graphics2D g2), et les méthodes print(), showPreview(), printPDF(). Pour chaque document de mon programme Java, j'applique draw() pour imprimer, afficher un aperçu et créer un fichier PDF pour chaque document. Mon problème est de savoir comment créer un PDF avec plusieurs pages à partir de cet objet Graphics. Je l'ai résolu en créant un fichier PDF pour chaque page, puis fusionner les fichiers dans un nouveau fichier. Mais il doit y avoir un meilleur moyen. je code suivant pour créer des PDF avec une page:Comment créer un PDF avec plusieurs pages à partir d'un objet Graphics avec Java et itext

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

Répondre

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

donc vous rendre votre interface ensemble N fois, et ne montrant une tranche de taille d'une page de celui-ci dans des endroits différents. C'est ce qu'on appelle "striping" dans le monde de l'imprimerie IIRC. Intelligent, mais il pourrait être plus efficace en PDF.

Rendez toute votre interface dans un énorme PdfTemplate (avec g2d), une fois. Dessinez ensuite ce modèle dans toutes vos pages de sorte que la partie que vous voulez soit visible à l'intérieur des marges de la page en cours ("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(); 
} 

L'espace de coordonnées PDF place 0,0 dans le coin inférieur gauche, et ces valeurs augmentent lorsque vous montez et vers la droite. PdfGraphis2D fait une bonne quantité de magie pour cacher cette différence à vous, mais nous devons encore y faire face un peu ici ... donc les coordonnées négatives dans la boîte englobante et les emplacements de dessin.

Tout cela est du code "retour de la serviette", et il est tout à fait possible que j'ai fait une erreur ou deux là-dedans ... mais c'est l'idée.

+0

Merci beaucoup, cela fonctionne avec les changements suivants. – Jan

+0

Quels changements? PS: c'est la partie où vous cliquez sur cette coche à côté de la bonne réponse, laissant les autres savoir qui avait raison (et donner à cette personne une certaine réputation). "Moi" dans ce cas. En outre, si vous posez plusieurs questions et ne les marquez jamais, les autres verront votre pourcentage de réponses médiocres et seront moins enclins à s'inquiéter car ils savent que vous ne leur donnerez pas de représentant même quand ils ont raison. –

+0

Désolé Mark, j'essaie de comprendre comment ce site fonctionne. Je ne savais pas que PdfContentByte pouvait être réutilisé pour chaque page. J'ai fait ces changements: PdfTemplate template = cb.createTemplate (_pageWidth, wholeHeight); g2 = template.createGraphics (_pageWidth, wholeHeight); ..... pour (int curPg = 1; curPg <= _numberOfPages; ++ curPg) { cb.addTemplate (hugeTempl, 0, -_pageHeight * (_numberOfPages - curPg)); document.newPage(); } – Jan

0

J'ai eu des problèmes en suivant le code ci-dessus (certaines des méthodes semblent avoir changé dans la version actuelle d'itextpdf). Voici ma solution:

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