Buscar..


Observaciones

En iText 5, introdujimos el concepto de eventos de página para permitir a los desarrolladores agregar un comportamiento específico cuando se abre un documento, cuando se abre una página nueva, cuando termina una página y cuando se cierra un documento.

En la documentación, dejamos muy claro que estaba prohibido agregar contenido en el método onStartPage() ; El contenido solo se puede agregar en el método onEndPage() . También dejamos muy en claro que el objeto Document pasado a los métodos de eventos de la página solo se aprobó con fines de solo lectura . Estaba prohibido utilizar document.add() incluso en el método onEndPage() .

Desafortunadamente, muchos desarrolladores ignoran completamente la documentación, lo que dio lugar a problemas como:

No puedo recordar cuántas veces me agité porque otro desarrollador publicó un duplicado de estas preguntas. Las personas a menudo se preguntan por qué reciben una respuesta áspera, pero no se dan cuenta de que un mínimo esfuerzo de su parte habría ahorrado a todos, incluso a ellos mismos, un montón de tiempo. Todas estas preguntas podrían haberse respondido diciendo "Lea el manual (usted sabe cuál)."

Otra opción fue una revisión completa de iText para evitar este tipo de problemas.

Debido al crecimiento orgánico de iText, la clase de evento de página también se había ampliado con una funcionalidad que no estaba relacionada con los eventos de página. Contuvo la funcionalidad de fragmentos genéricos , registró el inicio y el final de los párrafos, y así sucesivamente.

Lo que arreglamos en iText 7:

Eliminamos la funcionalidad de evento de la página.

Para todos los eventos con respecto a las páginas, ahora implementamos la interfaz IEventHandler , y usamos addEventHandler para agregar este controlador como PdfDocumentEvent al PdfDocument . En el ejemplo, usamos un evento END_PAGE , pero también podríamos haber usado un evento START_PAGE . Ya no importa si agrega contenido al principio o al final. Puedes leer más sobre esto en Handling events; configurando las preferencias del espectador y las propiedades del escritor, que es el capítulo 7 del tutorial de iText 7: Building Blocks

Mejoramos los bloques de construcción en el sentido de que los hicimos más jerárquicos (ver Antes de comenzar: Visión general de las clases e interfaces, que es la introducción del tutorial de iText 7: Bloques de construcción ). También introdujimos un conjunto de clases de Procesador, una para cada bloque de creación, y permitimos a los desarrolladores adaptar estos renderizadores para que un bloque de construcción muestre un comportamiento diferente cuando se procesa. Vea, por ejemplo, el ejemplo de renderizador en Agregar objetos AbstractElement (parte 1) que es el capítulo 7 en el tutorial de iText 7: Building Blocks .

Estos cambios simplifican la funcionalidad para los desarrolladores que no quieren (quieren) saber mucho sobre PDF y iText, mientras que al mismo tiempo ofrecen una gran flexibilidad a aquellos desarrolladores que no temen profundizar en el código de iText para crear un PDF exactamente de la forma en que lo quieren.

¿Quiere saber más? ¡Consigue el ebook gratis!

Text2PdfPageEvents.java (iText 5)

Supongamos que tenemos el siguiente archivo de texto: jekyll_hyde.txt

¿Cómo lo convertimos a un PDF que se parece a esto?

introduzca la descripción de la imagen aquí

Observe el borde azul que se agrega a los títulos y el número de página en la parte inferior de cada página. En iText 5, estos elementos se agregan mediante eventos de página:

class MyPageEvents extends PdfPageEventHelper {

    protected float startpos = -1;
    protected boolean title = true;

    public void setTitle(boolean title) {
        this.title = title;
    }

    @Override
    public void onEndPage(PdfWriter writer, Document document) {
        Rectangle pagesize = document.getPageSize();
        ColumnText.showTextAligned(
            writer.getDirectContent(),
            Element.ALIGN_CENTER,
            new Phrase(String.valueOf(writer.getPageNumber())),
            (pagesize.getLeft() + pagesize.getRight()) / 2,
            pagesize.getBottom() + 15,
            0);
        if (startpos != -1)
            onParagraphEnd(writer, document,
                pagesize.getBottom(document.bottomMargin()));
        startpos = pagesize.getTop(document.topMargin());
    }

    @Override
    public void onParagraph(PdfWriter writer, Document document,
        float paragraphPosition) {
        startpos = paragraphPosition;
    }

    @Override
    public void onParagraphEnd(PdfWriter writer, Document document,
        float paragraphPosition) {
        if (!title) return;
        PdfContentByte canvas = writer.getDirectContentUnder();
        Rectangle pagesize = document.getPageSize();
        canvas.saveState();
        canvas.setColorStroke(BaseColor.BLUE);
        canvas.rectangle(
            pagesize.getLeft(document.leftMargin()),
            paragraphPosition - 3,
            pagesize.getWidth() - document.leftMargin() - document.rightMargin(),
            startpos - paragraphPosition);
        canvas.stroke();
        canvas.restoreState();
    }
}

Podemos reutilizar el código para convertir un archivo de texto en un PDF desde el ejemplo de Text2Pdf.java (iText 5) , e introducir el evento de la página en PdfWriter :

public void createPdf(String dest)
throws DocumentException, IOException {
    Document document = new Document();
    PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(dest));
    MyPageEvents events = new MyPageEvents();
    writer.setPageEvent(events);
    document.open();
    BufferedReader br = new BufferedReader(new FileReader(TEXT));
    String line;
    Paragraph p;
    Font normal = new Font(FontFamily.TIMES_ROMAN, 12);
    Font bold = new Font(FontFamily.TIMES_ROMAN, 12, Font.BOLD);
    boolean title = true;
    while ((line = br.readLine()) != null) {
        p = new Paragraph(line, title ? bold : normal);
        p.setAlignment(Element.ALIGN_JUSTIFIED);
        events.setTitle(title);
        document.add(p);
        title = line.isEmpty();
    }
    document.close();
}

Fuente: developers.itextpdf.com

Text2PdfPageEvents1.java (iText 7)

Supongamos que tiene el siguiente archivo de texto: jekyll_hyde.txt

¿Cómo lo convertimos a un PDF que se parece a esto?

introduzca la descripción de la imagen aquí

Tenga en cuenta los números de página en la parte inferior de cada página. Estos se agregan utilizando una implementación de IEventHandler :

protected class Footer implements IEventHandler {

    @Override
    public void handleEvent(Event event) {
        PdfDocumentEvent docEvent = (PdfDocumentEvent) event;
        PdfDocument pdf = docEvent.getDocument();
        PdfPage page = docEvent.getPage();
        Rectangle pageSize = page.getPageSize();
        PdfCanvas pdfCanvas = new PdfCanvas(
            page.getLastContentStream(), page.getResources(), pdf);
        Canvas canvas = new Canvas(pdfCanvas, pdf, pageSize);
        float x = (pageSize.getLeft() + pageSize.getRight()) / 2;
        float y = pageSize.getBottom() + 15;
        canvas.showTextAligned(
            String.valueOf(pdf.getPageNumber(page)),
            x, y, TextAlignment.CENTER);
    }
}

Podemos reutilizar el ejemplo de Text2Pdf.java (iText 7) con solo dos cambios menores:

public void createPdf(String dest) throws IOException {
    PdfDocument pdf = new PdfDocument(new PdfWriter(dest));
    pdf.addEventHandler(PdfDocumentEvent.END_PAGE, new Footer());
    Document document = new Document(pdf)
        .setTextAlignment(TextAlignment.JUSTIFIED);
    BufferedReader br = new BufferedReader(new FileReader(TEXT));
    String line;
    PdfFont normal = PdfFontFactory.createFont(FontConstants.TIMES_ROMAN);
    PdfFont bold = PdfFontFactory.createFont(FontConstants.TIMES_BOLD);
    boolean title = true;
    Border border = new SolidBorder(Color.BLUE, 1);
    while ((line = br.readLine()) != null) {
        document.add(new Paragraph(line)
            .setFont(title ? bold : normal)
            .setBorder(title ? border : Border.NO_BORDER));
        title = line.isEmpty();
    }
    document.close();
}

handleEvent() un controlador de eventos que activará el método handleEvent() de la clase Footer cada vez que una página finalice. También definimos un borde para los objetos de Paragraph que se usan para un título.

Fuente: developers.itextpdf.com y el tutorial de iText 7: Building Blocks .

Text2PdfPageEvents2.java

Supongamos que tiene el siguiente archivo de texto: jekyll_hyde.txt

¿Cómo lo convertimos a un PDF que se parece a esto?

introduzca la descripción de la imagen aquí

Tenga en cuenta que esto es muy similar a lo que teníamos antes, pero el borde de los títulos ahora tiene esquinas redondeadas. Creamos un ParagraphRenderer personalizado para lograr esto, y creamos un objeto TitleParagraph que usa ese procesador:

public class TitleParagraph extends Paragraph {

    public TitleParagraph(String line) {
        super(line);
        try {
            setFont(PdfFontFactory.createFont(FontConstants.TIMES_BOLD));
        }
        catch (IOException ioe) {
        }
    }

    @Override
    protected IRenderer makeNewRenderer() {
        return new ParagraphRenderer(this) {
            @Override
            public void drawBorder(DrawContext drawContext) {
                Rectangle occupiedAreaBBox = getOccupiedAreaBBox();
                float[] margins = getMargins();
                Rectangle rectangle = applyMargins(occupiedAreaBBox, margins, false);
                PdfCanvas canvas = drawContext.getCanvas();
                canvas.roundRectangle(rectangle.getX() - 1, rectangle.getY() - 1,
                rectangle.getWidth() + 2, rectangle.getHeight() + 2, 5).stroke();
            }
        };
    } 
}

Nuestro código para convertir texto a PDF es muy simple ahora. Ya no tenemos que establecer la fuente en negrita para los títulos y ya no tenemos que definir un borde:

public void createPdf(String dest) throws IOException {
    PdfDocument pdf = new PdfDocument(new PdfWriter(dest));
    pdf.addEventHandler(PdfDocumentEvent.END_PAGE, new Footer());
    Document document = new Document(pdf)
        .setTextAlignment(TextAlignment.JUSTIFIED);
    BufferedReader br = new BufferedReader(new FileReader(TEXT));
    String line;
    PdfFont normal = PdfFontFactory.createFont(FontConstants.TIMES_ROMAN);
    boolean title = true;
    Border border = new SolidBorder(Color.BLUE, 1);
    while ((line = br.readLine()) != null) {
        if (title)
            document.add(new TitleParagraph(line));
        else
            document.add(new Paragraph(line).setFont(normal));
        title = line.isEmpty();
    }
    document.close();
}

Fuente: developers.itextpdf.com y el tutorial de iText 7: Building Blocks .



Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow