如何在同一页面中切换不同的iText文档渲染器

问题描述 投票:0回答:1

这种情况是,在页面的开始处,元素应绘制在一列中,此后,同一页面中的元素应绘制在两列中。

到目前为止,根据iText示例“ c02e10_jekyllhydev6”,我可以在页面之间切换不同的渲染器,这意味着首先应用DocumentRenderer,然后添加Next Page的AreaBreak,然后在新页面中应用ColumnDocumentRenderer。

“此处是创建的PDF:”

代码:

PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
Document doc = new Document(pdfDoc, PageSize.A4);
doc.SetMargins(36, 36, 36, 36);

Paragraph p = new Paragraph();
p.SetBorder(new SolidBorder(0.5f));
for (int i = 1; i <= 500; i++)
{
    p.Add(new Text(i + " "));
}
doc.Add(p);
**doc.Add(new AreaBreak(AreaBreakType.NEXT_PAGE));**


PageSize ps = PageSize.A4;
var effectiveArea = doc.GetPageEffectiveArea(PageSize.A4);
float columnHeight = effectiveArea.GetHeight();
//Define column areas
Rectangle[] columns = new Rectangle[] {
    new Rectangle(36, 36, 200, columnHeight),
    new Rectangle(36 + 200 + 20, 36, effectiveArea.GetWidth()- 200 - 20, columnHeight)
};

ColumnDocumentRenderer renderer1 = new ColumnDocumentRenderer(doc, new Rectangle[] { columns[0] });
doc.SetRenderer(renderer1);
**doc.Add(new AreaBreak(AreaBreakType.LAST_PAGE));**
Paragraph p1 = new Paragraph();
p1.SetBorder(new SolidBorder(0.5f));
for (int i = 1; i <= 500; i++)
{
    p1.Add(new Text(i + " "));
}
doc.Add(p1);

ColumnDocumentRenderer renderer2 = new ColumnDocumentRenderer(doc, new Rectangle[] { columns[1] });
doc.SetRenderer(renderer2);
Paragraph p2 = new Paragraph();
for (int i = 1; i <= 1000; i++)
{
    p2.Add(new Text(i + " "));
}
doc.Add(p2);

//renderer2.SetColumns(new Rectangle[] { new Rectangle(36, 36, effectiveArea.GetWidth(), effectiveArea.GetHeight())});

doc.Add(new AreaBreak(AreaBreakType.NEXT_PAGE));
DocumentRenderer renderer3 = new DocumentRenderer(doc);
doc.SetRenderer(renderer3);
doc.Add(new AreaBreak(AreaBreakType.LAST_PAGE));
Paragraph p3 = new Paragraph();
for (int i = 1; i <= 1000; i++)
{
    p3.Add(new Text(i + " "));
}
doc.Add(p3);

doc.Close();

如果未在文档中添加AreaBreak,则具有不同渲染器的内容将重叠。

[根据Alexey在this case中的评论,似乎可以在同一页面中切换不同的渲染器而不会出现内容重叠。

要适当地处理此问题,您必须将要切换到的渲染器的currentArea更新为刚使用完的先前渲染器的currentArea。您可以通过扩展提供的标准渲染器,或调用renderer.getCurrentArea()并修改bBox来做到这一点。

但是我不知道如何根据上述指南实现它。

c# itext itext7
1个回答
0
投票

在您的情况下,ColumnDocumentRenderer中没有必要-该渲染器是为以下情况而创建的:您希望将内容放在一页范围内的列中,然后再转到下一页等。在跨越许多页面的列中布置内容,这相当于只为DocumentRenderer设置适当的边距,而不是将列传递给ColumnDocumentRenderer

要临时切换渲染器,您确实确实需要调整其currentArea字段和currentPageNumber。请注意,不能保证下面的解决方案在所有复杂情况下和所有iText版本中都不能使用。这仅是有关如何实现所需内容的指南,而不是针对所有情况的完整解决方案。

我们需要的帮助器渲染器类非常简单-它允许自定义当前区域:

private class ExtendedDocumentRenderer : DocumentRenderer {
    public ExtendedDocumentRenderer(Document document, RootLayoutArea currentArea) : base(document) {
        this.currentArea = new RootLayoutArea(currentArea.GetPageNumber(), currentArea.GetBBox().Clone());
        this.currentPageNumber = this.currentArea.GetPageNumber();
    }
}

现在,我已经调整了您的代码以摆脱ColumnDocumentRenderer,而改用普通的DocumentRenderer。您只需要调整文档边距并正确地重新计算当前区域(页面上剩余的空间):

Document doc = new Document(pdfDocument);


Paragraph p = new Paragraph();
p.SetBorder(new SolidBorder(0.5f));
for (int i = 1; i <= 500; i++)
{
    p.Add(new Text(i + " "));
}
doc.Add(p);

RootLayoutArea endOfFullWidthContentArea = (RootLayoutArea) doc.GetRenderer().GetCurrentArea();

ExtendedDocumentRenderer renderer1 = new ExtendedDocumentRenderer(doc, 
    new RootLayoutArea(endOfFullWidthContentArea.GetPageNumber(), endOfFullWidthContentArea.GetBBox().Clone().SetWidth(200)));
doc.SetRightMargin(doc.GetRightMargin() + doc.GetPageEffectiveArea(PageSize.A4).GetWidth() - 200);
doc.SetRenderer(renderer1);
Paragraph p1 = new Paragraph();
p1.SetBorder(new SolidBorder(0.5f));
for (int i = 1; i <= 500; i++)
{
    p1.Add(new Text(i + " "));
}
doc.Add(p1);

ExtendedDocumentRenderer renderer2 = new ExtendedDocumentRenderer(doc,
    new RootLayoutArea(endOfFullWidthContentArea.GetPageNumber(),
        endOfFullWidthContentArea.GetBBox().Clone().MoveRight(200)
            .SetWidth(endOfFullWidthContentArea.GetBBox().GetWidth() - 200)));
doc.SetRightMargin(36);
doc.SetLeftMargin(200 + 36);
doc.SetRenderer(renderer2);
Paragraph p2 = new Paragraph();
for (int i = 1; i <= 1000; i++)
{
    p2.Add(new Text(i + " "));
}
doc.Add(p2);

// Compute which free area is lower in the document
RootLayoutArea areaColumn1 = (RootLayoutArea) renderer1.GetCurrentArea();
RootLayoutArea areaColumn2 = (RootLayoutArea) renderer2.GetCurrentArea();
RootLayoutArea downArea = areaColumn1.GetPageNumber() > areaColumn2.GetPageNumber() ? areaColumn1 : 
    (areaColumn1.GetPageNumber() < areaColumn2.GetPageNumber() ? areaColumn2 : 
        (areaColumn1.GetBBox().GetTop() < areaColumn2.GetBBox().GetTop() ? areaColumn1 : areaColumn2));

doc.SetMargins(36, 36, 36, 36);
DocumentRenderer renderer3 = new ExtendedDocumentRenderer(doc, 
    new RootLayoutArea(downArea.GetPageNumber(), downArea.GetBBox().Clone().SetX(36).SetWidth(doc.GetPageEffectiveArea(PageSize.A4).GetWidth())));
doc.SetRenderer(renderer3);

Paragraph p3 = new Paragraph();
for (int i = 1; i <= 1000; i++)
{
    p3.Add(new Text(i + " "));
}
doc.Add(p3);

doc.Close();

结果如下:

result

© www.soinside.com 2019 - 2024. All rights reserved.