我试图使用itext7使用EventHandlers创建动态页面头。我正在使用下面的代码:
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”,它为文档的每个页面呈现动态页面头。
最初,我将页面标题设置为“第一个标题”,并将文本“添加第一个内容”添加到文档中50次。然后,我添加了区域分隔符,在呈现之前的内容之后,页面的进一步部分将为空,任何进一步的内容都将在新页面中呈现。然后,我将页面标题更改为“第二个标题”,并将文本“添加第二个内容”添加到文档中15次。
因此,根据上面的代码,页面标题“第二个标题”应该仅从显示文本“添加的第二个内容”的页面中呈现。但是,“第二个标题”呈现在上一页中,其中显示文本“添加的第一内容”,如下所示:
iText7动态头问题:
看起来,iText 7.0.1中的事件处理机制存在一些问题。
有什么办法解决这个问题吗?任何帮助都将不胜感激。
发布于 2017-02-03 18:13:52
您正在使用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的问题。
https://stackoverflow.com/questions/42027642
复制相似问题