2

我正在使用 iText7 创建一个包含多个部分的文档。有些部分要正常格式化,但有些要格式化成列。我可以通过使用 ColumnDocumentRenderer 对象将其正确格式化为列,但是当我这样做时,整个文档都设置为使用列。有没有办法让 iText 即时交换要使用的渲染器?

当我尝试动态更换渲染器时,我得到一个空指针异常 (com.itextpdf.kernel.pdf.PdfDictionary.get(PdfDictionary.java:482))。

PdfDocument pdf = new PdfDocument(new PdfWriter(targetFile));
Document document = new Document(pdf);
DocumentRenderer defRender = new DocumentRenderer(document);
document.setRenderer(defRender);
ColumnDocumentRenderer dictRender = getColumnRender();

while (<CONDITION>) {
    document.setRenderer(dictRender);
    document.add(new Paragraph("THIS IS NORMAL TEXT"));
    document.add(new Paragraph("THIS IS NORMAL TEXT"));
    document.add(new Paragraph("THIS IS NORMAL TEXT"));
    <...> 
    document.setRenderer(defRender);
    document.add(new Paragraph("THIS IS COLUMN TEXT"));
    document.add(new Paragraph("THIS IS COLUMN TEXT"));
    document.add(new Paragraph("THIS IS COLUMN TEXT"));
    <...>
}

将渲染器设置为 dictRender 后,第一个 document.add() 语句在 com.itextpdf.kernel.pdf.PdfDictionary.get(PdfDictionary.java:482) 处引发空指针错误。

我不想创建多个不同的 PDF 文件,但我认为这可能是我最终不得不做的。感谢您在这里的任何帮助。

4

1 回答 1

4

发生异常是因为默认情况下会尽快刷新页面内容以节省内存。

为了避免立即刷新内容,有一个DocumentRendererColumnDocumentRenderer构造函数的参数。

因此,例如,要创建一个DocumentRenderer关闭立即刷新的,您必须按如下方式创建它:

DocumentRenderer defRender = new DocumentRenderer(document, false);

对于ColumnDocumentRenderer.

接下来,由于您已经关闭了自动刷新并自己更改了渲染器,因此在代码的最后,就在 之前document.close();,您必须手动刷新渲染器:

defRender.flush();
dictRender.flush();

现在内容出现了,尽管由于内容重叠,结果仍然可能看起来很难看。这取决于开发人员来解决,因为两个渲染器是独立的实例,并且它们彼此保持currentArea独立。为了适当地处理这个问题,您必须使用刚刚完成的前一个渲染器来更新currentArea您要切换到的渲染器。currentArea您可以通过扩展标准提供的渲染器或调用renderer.getCurrentArea()和修改bBox.

于 2016-08-11T07:48:30.310 回答