【问题标题】:iText 7 dynamic page header issueiText 7 动态页眉问题
【发布时间】:2017-02-03 15:28:07
【问题描述】:

我正在尝试使用 EventHandlers 创建带有 itext7 的动态页眉。我为此使用以下代码:

    public static void main(String[] args) throws Exception {
    File file = new File("C:\\Test\\variable_header.pdf");
    file.getParentFile().mkdirs();
    new VariableHeader().manipulatePdf(DEST);
}

protected void manipulatePdf(String dest) throws Exception {
    PdfDocument pdfDoc = new PdfDocument(new PdfWriter(DEST));
    Document doc = new Document(pdfDoc);
    VariableHeaderEventHandler handler = new VariableHeaderEventHandler();
    pdfDoc.addEventHandler(PdfDocumentEvent.END_PAGE, handler);
    handler.setHeader("First Header");
    for (int i = 1; i <= 50; i++) {
        doc.add(new Paragraph("Added First content"));
     }
    doc.add(new AreaBreak());
    handler.setHeader("Second Header");
    for (int i = 1; i <= 15; i++) {
        doc.add(new Paragraph("Added Second content"));
    }
    doc.close();
}

protected class VariableHeaderEventHandler implements IEventHandler {
    protected String header;

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

    @Override
    public void handleEvent(Event event) {
        PdfDocumentEvent documentEvent = (PdfDocumentEvent) event;
        try {
            new PdfCanvas(documentEvent.getPage())
                    .beginText()
                    .setFontAndSize(PdfFontFactory.createFont(FontConstants.HELVETICA), 12)
                    .moveText(450, 806)
                    .showText(header)
                    .endText()
                    .stroke();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

在这里,我创建了“VariableHeaderEventHandler”,它为文档的每一页呈现动态页眉。

最初,我将页眉设置为“First Header”,并将“Added First content”文本添加到文档中 50 次。然后我添加了区域中断,它在呈现之前的内容后将页面的另一部分留空,并且任何进一步的内容都将在新页面中呈现。然后我将页眉更改为“第二页眉”,并在文档中添加了文本“添加第二个内容”15次。

所以根据上面的代码,页面标题“第二个标题”应该只从显示文本“添加的第二个内容”的页面呈现。但是“第二个标题”是在上一页中呈现的,其中显示了“添加的第一个内容”文本,如下所示:

iText7 动态标题问题:

iText 7.0.1 中的事件处理机制似乎存在一些问题。

有没有办法解决这个问题?任何帮助,将不胜感激。

【问题讨论】:

    标签: itext7


    【解决方案1】:

    您正在使用PdfDocument 的低级事件以及通过Document 的高级布局。当页面刷新到输出流时触发END_PAGE 事件。尽管低级PdfDocument 和高级Document 是相关的,但没有约定Document 在进入新页面后立即刷新页面。事实上,Document 默认情况下会刷新页面有一些延迟,这是更细粒度的布局功能所需要的。页面刷新有一些延迟的事实导致新设置的标题出现在具有第一类内容的“旧”页面上。所以这是预期的行为,至少现在是这样。

    有很多方法可以绕过这种行为并实现您想要的。我将讲述其中之一。

    AreaBreak 添加到Document 后,您可以向DocumentRenderer 询问当前可用于渲染其余内容的区域,该区域将包含当前页码:

    doc.add(new AreaBreak());
    int secondContentStartPageNumber = doc.getRenderer().getCurrentArea().getPageNumber();
    

    然后您可以将该信息传递给您的事件处理程序:

    handler.setSecondAreaStartPage(secondContentStartPageNumber);
    

    并在决定为页面输出哪个标题时使用该信息:

    int pageNumber = documentEvent.getDocument().getPageNumber(documentEvent.getPage());
    String textToShow = pageNumber < secondAreaStartPage ? firstHeader : secondHeader;
    

    完整的VariableHeaderEventHandler 类如下所示:

    protected class VariableHeaderEventHandler implements IEventHandler {
        private String firstHeader = "First Header";
        private String secondHeader = "Second Header";
        private int secondAreaStartPage = Integer.MAX_VALUE;
    
        public void setSecondAreaStartPage(int newValue) {
            secondAreaStartPage = newValue;
        }
    
        @Override
        public void handleEvent(Event event) {
            PdfDocumentEvent documentEvent = (PdfDocumentEvent) event;
            int pageNumber = documentEvent.getDocument().getPageNumber(documentEvent.getPage());
            try {
                new PdfCanvas(documentEvent.getPage())
                        .beginText()
                        .setFontAndSize(PdfFontFactory.createFont(FontConstants.HELVETICA), 12)
                        .moveText(450, 806)
                        .showText(pageNumber < secondAreaStartPage ? firstHeader : secondHeader)
                        .endText()
                        .stroke();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    

    当然对于两个以上区域的情况,代码会变得更复杂,但这更像是一个编程练习,而不是关于 iText 的问题。

    【讨论】:

    • 这确实比相同任务的普通 itext 5 实现更复杂。特别是如果您想要页眉或页脚中的当前章节和部分或类似的动态...
    • 我在页脚的部分标题中遇到了同样的问题;它在 iText5 中工作得很好,然后我把它移植过来,我一直在扯头发,试图弄清楚为什么我调用 newPage 而没有触发事件:P 感谢您的解决方案......和@ mkl,我绝对同意,在 iText5 中执行此操作要简单得多....
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-25
    • 2023-03-12
    • 1970-01-01
    • 2020-04-26
    • 1970-01-01
    相关资源
    最近更新 更多