Поиск…


замечания

В iText 5 мы ввели концепцию событий страницы, чтобы разработчики могли добавлять определенное поведение при открытии документа, когда открывается новая страница, когда страница заканчивается и когда документ закрывается.

В документации мы ясно дали понять, что было запрещено добавлять контент в метод onStartPage() ; содержимое может быть добавлено только в метод onEndPage() . Мы также ясно дали понять, что объект Document переданный методам событий страницы, передавался только для чтения . Запрещено использовать document.add() даже в onEndPage() .

К сожалению, многие разработчики полностью игнорируют документацию, которая привела к таким проблемам, как:

Я не помню, сколько раз я волновался, потому что еще один разработчик разместил дубликат этих вопросов. Люди часто задаются вопросом, почему они получают суровый ответ, но они не понимают, что минимальные усилия с их стороны спасли бы всех, включая самих себя, много времени. На все эти вопросы можно было ответить, сказав «Прочитайте руководство (вы знаете, какое)».

Другим вариантом был полный пересмотр iText, чтобы избежать подобных проблем.

Из-за органического роста iText класс событий страницы также был расширен функциональностью, не связанной с событиями страницы. Он содержал общую функциональность блока , он регистрировал начало и конец абзацев и т. Д.

Что мы зафиксировали в iText 7:

Мы удалили функциональность события страницы.

Для всех событий в отношении страниц мы теперь реализуем интерфейс IEventHandler , и мы используем addEventHandler для добавления этого обработчика в виде PdfDocumentEvent к PdfDocument . В этом примере мы используем событие END_PAGE , но мы также могли использовать событие START_PAGE . Не имеет значения, добавляете ли вы контент в начале или в конце. Подробнее об этом можно прочитать в разделе Обработка событий; настройки параметров просмотра и свойств записи, которые являются главой 7 в учебнике iText 7: Building Blocks .

Мы улучшили строительные блоки в том смысле, что сделали их более иерархичными (см. Перед тем, как мы начнем: Обзор классов и интерфейсов, которые представляют собой введение в учебник iText 7: Building Blocks ). Мы также представили набор классов Renderer, по одному для каждого строительного блока, и мы разрешаем разработчикам адаптировать эти средства визуализации так, чтобы строительный блок показывал другое поведение при визуализации. См., Например, пример рендеринга в разделе Добавление объектов AbstractElement (часть 1), который является главой 7 в учебнике iText 7: Building Blocks .

Эти изменения упрощают функциональность для разработчиков, которые (не хотят) много знать о PDF и iText, и в то же время предлагают изобилие возможностей для тех разработчиков, которые не боятся углубляться в код iText, чтобы создать PDF точно так, как они этого хотят.

Хотите узнать больше? Получите бесплатную электронную книгу!

Text2PdfPageEvents.java (iText 5)

Предположим, что у нас есть следующий текстовый файл: jekyll_hyde.txt

Как мы преобразуем его в PDF, который выглядит так:

введите описание изображения здесь

Обратите внимание на синюю рамку, которая добавляется к заголовкам, и номер страницы внизу каждой страницы. В iText 5 эти элементы добавляются с помощью событий страницы:

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

Мы можем повторно использовать код для преобразования текстового файла в PDF из примера Text2Pdf.java (iText 5) и ввести событие страницы в 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();
}

Источник: developers.itxtpdf.com

Text2PdfPageEvents1.java (iText 7)

Предположим, что у вас есть следующий текстовый файл: jekyll_hyde.txt

Как мы преобразуем его в PDF, который выглядит так:

введите описание изображения здесь

Обратите внимание на номера страниц внизу каждой страницы. Они добавляются с помощью реализации 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);
    }
}

Мы можем повторно использовать пример Text2Pdf.java (iText 7) только с двумя незначительными изменениями:

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() класса Footer каждый раз, когда страница заканчивается. Мы также определяем границу для объектов Paragraph , которые используются для названия.

Источник: developers.itxtpdf.com и учебник iText 7: Building Blocks .

Text2PdfPageEvents2.java

Предположим, что у вас есть следующий текстовый файл: jekyll_hyde.txt

Как мы преобразуем его в PDF, который выглядит так:

введите описание изображения здесь

Обратите внимание, что это очень похоже на то, что мы имели раньше, но граница заголовков теперь имеет закругленные углы. Для этого мы создали пользовательский ParagraphRenderer , и мы создали объект TitleParagraph который использует этот рендерер:

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

Наш код для преобразования текста в PDF очень прост. Нам больше не нужно выделять шрифт для заголовков, и нам больше не нужно определять границу:

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

Источник: developers.itxtpdf.com и учебник iText 7: Building Blocks .



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow