Как добавить нижний колонтитул страницы X из Y в iText 7

Я пытаюсь понять, как добавить нижний колонтитул «Страница X из Y» на каждую страницу документа PDF, который я создаю с помощью iText 7.

Использование IEventHandler для генерации части «Страница X» кажется довольно простым - это бит «of Y», с которым я борюсь. Я хочу избежать создания всего документа дважды, чтобы узнать, сколько в нем страниц, так как это значительно снизит производительность!

Я нашел решение для этого в iText 5 здесь: Нумерация страниц PDF в Java и iText, но iText 7 - это полная переработка iText с совершенно другим интерфейсом, и пока мне не удалось найти аналогичный iText 7 примеры.


person Dan King    schedule 26.07.2016    source источник
comment
Может ли кто-нибудь создать тег iText7, который я могу добавить к нему, так как у меня недостаточно репутации! :-( Тег iText не особенно полезен при поиске вопросов и ответов iText7, так как iText 5 и iText 7 - совершенно разные звери!   -  person Dan King    schedule 26.07.2016
comment
Согласно meta.stackexchange.com/questions/85358/ и meta.stackoverflow.com/questions/299598/, itext7 tag может быть полезным. Я не против этого. Однако модераторы StackOverflow очень быстро избавятся от такого тега, не зная подробностей.   -  person Amedee Van Gasse    schedule 26.07.2016
comment
Я только что создал тег, посмотрим, сколько он проживет. Если честно, я не оптимистичен.   -  person Amedee Van Gasse    schedule 26.07.2016
comment
Спасибо @AmedeeVanGasse! Первая опубликованная вами ссылка имеет это в правильном ответе: я бы использовал теги версии только тогда, когда содержание вопроса безвозвратно привязано к определенной версии чего-либо и никогда не может иметь отношения к более ранним версиям или более поздним версиям, что определенно применимо в этом случае, поскольку iText 5 и 7 полностью отличаются друг от друга. Другой вопрос имеет аналогичный ответ. Так что надеюсь ...! :-)   -  person Dan King    schedule 26.07.2016
comment
Надеюсь, тег iText7 продержится! Новая версия не только намного мощнее, но и отличается от других в использовании. У людей будет много вопросов по этому поводу (я знаю, что задам!)   -  person Draque Thompson    schedule 10.08.2016
comment
Отвечает ли это на ваш вопрос? Нумерация страниц PDF в Java и iText   -  person Ravindra Gullapalli    schedule 04.05.2021


Ответы (1)


ответ, который вы нашли для iText 5, ссылается на MovieCountries1. Этот пример был переписан для iText 7 как Listing_05_20_MovieCountries1. Его основной код:

protected PdfFont bold;
protected PdfFont italic;
protected PdfFont normal;

protected PdfFormXObject template;

public void manipulatePdf(String dest) throws IOException, SQLException {
    PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
    Document doc = new Document(pdfDoc, new PageSize(PageSize.A4), true);
    doc.setMargins(54, 36, 36, 36);

    bold = PdfFontFactory.createFont(FontConstants.HELVETICA_BOLD);
    italic = PdfFontFactory.createFont(FontConstants.HELVETICA_OBLIQUE);
    normal = PdfFontFactory.createFont(FontConstants.HELVETICA);

    template = new PdfFormXObject(new Rectangle(550, 803, 30, 30));
    PdfCanvas canvas = new PdfCanvas(template, pdfDoc);

    HeaderHandler headerHandler = new HeaderHandler();
    pdfDoc.addEventHandler(PdfDocumentEvent.START_PAGE, headerHandler);

    ... ADD CONTENT ...

    canvas.beginText();
    try {
        canvas.setFontAndSize(PdfFontFactory.createFont(FontConstants.HELVETICA), 12);
    } catch (IOException e) {
        e.printStackTrace();
    }
    canvas.moveText(550, 803);
    canvas.showText(Integer.toString(pdfDoc.getNumberOfPages()));
    canvas.endText();
    canvas.release();

    doc.close();
}

public class HeaderHandler implements IEventHandler {
    protected String country;

    @Override
    public void handleEvent(Event event) {
        PdfDocumentEvent docEvent = (PdfDocumentEvent) event;
        PdfPage page = docEvent.getPage();
        int pageNum = docEvent.getDocument().getPageNumber(page);
        PdfCanvas canvas = new PdfCanvas(page);
        canvas.beginText();
        try {
            canvas.setFontAndSize(PdfFontFactory.createFont(FontConstants.HELVETICA), 12);
        } catch (IOException e) {
            e.printStackTrace();
        }
        canvas.moveText(34, 803);
        canvas.showText(country);
        canvas.moveText(450, 0);
        canvas.showText(String.format("Page %d of", pageNum));
        canvas.endText();
        canvas.stroke();
        canvas.addXObject(template, 0, 0);
        canvas.release();
    }

    public void setHeader(String country) {
        this.country = country;
    }
}

Вы также найдете там перезаписи многих других семплов.


Как заметил @Bruno в комментарии, есть даже немного другой пример, который был действительно создан для iText 7 (в отличие от приведенного выше примера, который является портом примера iText 5).

Это пример, сопровождающий глава 7 iText 7: стандартные блоки учебник. Он использует showTextAligned(), чтобы убедиться, что «Страница X из» точно совпадает с «Y», независимо от того, сколько цифр у X и Y, ср. его метод прослушивателя событий конца страницы:

public void handleEvent(Event event) {
    PdfDocumentEvent docEvent = (PdfDocumentEvent) event;
    PdfDocument pdf = docEvent.getDocument();
    PdfPage page = docEvent.getPage();
    int pageNumber = pdf.getPageNumber(page);
    Rectangle pageSize = page.getPageSize();
    PdfCanvas pdfCanvas = new PdfCanvas(
        page.newContentStreamBefore(), page.getResources(), pdf);
    Canvas canvas = new Canvas(pdfCanvas, pdf, pageSize);
    Paragraph p = new Paragraph()
        .add("Page ").add(String.valueOf(pageNumber)).add(" of");
    canvas.showTextAligned(p, x, y, TextAlignment.RIGHT);
    pdfCanvas.addXObject(placeholder, x + space, y - descent);
    pdfCanvas.release();
}

(C07E03_PageXofY.java, класс обработчика событий PageXofY)

person mkl    schedule 27.07.2016
comment
Это действительно полезно - спасибо @mkl! Однако вы пропустили одну из ключевых частей - где устанавливается общее количество страниц: canvas.showText(Integer.toString(pdfDoc.getNumberOfPages())); - person Dan King; 27.07.2016
comment
Я играл со своей адаптированной версией этого примера и думаю, что в нем есть пара ошибок. canvas.moveText(450,0) помещает страницу X текста в самый низ страницы без полей, что выглядит немного странно, но, что более важно, canvas.moveText(550,803) дальше вверх, счетчик страниц помещается в правом верхнем углу документа, а не после Страница X текста. - person Dan King; 05.08.2016
comment
canvas.moveText(450,0) помещает страницу X текста в самый низ страницы без полей - нет, вы забыли принять во внимание canvas.moveText(34, 803) две строки перед этим. Таким образом, страница% d of эффективно отрисовывается в (484, 803), который явно является областью заголовка. canvas.moveText(550,803) далее вверх, помещает счетчик страниц в правый верхний угол документа, а не после страницы X текста - правый верхний угол находится после страницы X текста. - person mkl; 05.08.2016
comment
Ах - хорошо, моя ошибка. Я удалил часть страны, так как я этого не хотел, и не подумал, что moveText () является относительным. - person Dan King; 05.08.2016
comment
Я изо всех сил пытаюсь понять взаимосвязь между холстом и шаблоном (PdfFormXObject). Шаблон определен с местоположением 550,803, но затем кажется необходимым переместиться в это место на холсте (которое инкапсулирует (?) Шаблон) перед записью количества страниц. Что на самом деле здесь происходит? Что более полезно думать о шаблоне как о окне на холсте? - person Dan King; 05.08.2016
comment
Что более полезно думать о шаблоне как о окне на холсте? - Звучит как хорошая идея. Холст формы xobject представляет собой бесконечную плоскость (ну, на самом деле он ограничен, но очень и очень велик), а форма xobject определяет прямоугольник на холсте, содержимое которого в конечном итоге будет видимым. - person mkl; 05.08.2016
comment
Привет, я пишу последнюю главу iText 7: строительные блоки учебник. Текст еще не закончен, но вы уже можете найти PageXofY в разделе примеров в главе 7. Он немного отличается от кода @ mkl. Я использую showTextAligned(), чтобы убедиться, что страница X хорошо совпадает с Y, независимо от того, сколько цифр у X и Y. - person Bruno Lowagie; 16.08.2016