2011-03-13 9 views
7

Mam klasę abstrakcyjną z abstrakcyjnym rysunkiem metod (Graphics2D g2) i metodami print(), showPreview(), printPDF(). Dla każdego dokumentu w moim programie Java implementuję funkcję draw(), dzięki czemu mogę drukować, wyświetlać podgląd i tworzyć pliki PDF dla każdego dokumentu. Mój problem polega na tym, jak utworzyć plik PDF z wieloma stronami z tego obiektu Graphics. Rozwiązałem go, tworząc plik PDF dla każdej strony, a następnie scalając pliki w jeden nowy plik. Ale musi być lepszy sposób. Mam następujący kod do tworzenia PDF z jednej strony:Tworzenie pliku PDF z wieloma stronami z obiektu Graphics za pomocą Javy i itextu

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

Odpowiedz

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

Więc renderowania cały interfejs n razy, a tylko pokazuje kawałek stronę rozmiarze go w różnych miejscach. To się nazywa "striping" w IIRC w świecie druku. Sprytnie, ale może być bardziej wydajny w PDF.

Jednorazowo odtwórz cały interfejs w jeden ogromny plik PdfTemplate (z g2d). Następnie narysuj ten szablon na wszystkich stronach tak, aby żądany fragment był widoczny wewnątrz marginesów bieżącej strony ("pole multimediów").

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 układzie współrzędnych wyznacza 0,0 w lewym dolnym rogu, a wartości te zwiększają jak idziesz w górę iw prawo. PdfGraphis2D robi sporą ilość magii, aby ukryć tę różnicę przed tobą, ale wciąż musimy sobie z tym poradzić trochę ... w ten sposób ujemne współrzędne w obwiedni i miejscach rysowania.

To kodowanie "z tyłu serwetki" i jest całkowicie możliwe, że popełniłem błąd lub dwa ... ale taki jest pomysł.

+0

Dziękuję bardzo, działa z następującymi zmianami. – Jan

+0

Jakie zmiany? PS: jest to część, w której klikasz ten pusty znacznik obok poprawnej odpowiedzi, pozwalając innym znać, kto miał rację (i dawać tej osobie jakąś reputację). "Ja" w tym przypadku. Ponadto, jeśli zadasz wiele pytań i nigdy nie oznaczysz ich odpowiedzi, inni będą widzieć twój niski procent odpowiedzi i będą mniej skłonni do kłopotów, ponieważ wiedzą, że nie dasz im powtórzenia, nawet jeśli mają rację. –

+0

Przykro nam, Mark, próbuję zrozumieć, jak działa ta strona. Nie zdawałem sobie sprawy, że PdfContentByte może być ponownie użyty dla każdej strony. Wprowadziłem zmiany: Pdf Szablon szablonu = cb.createTemplate (_pageWidth, wholeHeight); g2 = template.createGraphics (_pageWidth, wholeHeight); ..... dla (int curPg = 1; curPg <= _numberOfPages; ++ curPg) { cb.addTemplate (hugeTempl, 0, -_pageHeight * (_numberOfPages - curPg)); document.newPage(); } – Jan

0

Wystąpił problem z postępowaniem zgodnie z powyższym kodem (niektóre metody uległy zmianie w bieżącej wersji itextpdf). Oto moje rozwiązanie:

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(); 
    } 
Powiązane problemy