我正在用iText7进行一些测试,并且有一种情况,我需要在顶部放置DocumentRenderer段落,然后在同一页面上以其下面的2列启动ColumnDocumentRender。我遇到的问题是,当我更改同一页面上的内容时,它将与DocumentRenderer中的内容与ColumnDocumentRenderer中的内容重叠。我相信这是因为一个渲染器不知道其他渲染器,并且内容从页面顶部开始。我遵循了this tutorial,但是它仅显示了如何向下一页添加内容。它说
我们将不得不指示iText不要将内容刷新到 OutputStream
但是谁能确切地告诉我我们如何实现这一目标?
public void createPdf(String dest) throws IOException {
PdfDocument pdf = new PdfDocument(new PdfWriter(dest));
Document document = new Document(pdf);
Paragraph p = new Paragraph()
.add("Be prepared to read a story about a London lawyer "
+ "named Gabriel John Utterson who investigates strange "
+ "occurrences between his old friend, Dr. Henry Jekyll, "
+ "and the evil Edward Hyde.");
document.add(p);
document.add(new AreaBreak(AreaBreakType.NEXT_PAGE));
... // Define column areas
document.setRenderer(new ColumnDocumentRenderer(document, columns));
document.add(new AreaBreak(AreaBreakType.LAST_PAGE));
... // Add novel in two columns
document.add(new AreaBreak(AreaBreakType.NEXT_PAGE));
document.setRenderer(new DocumentRenderer(document));
document.add(new AreaBreak(AreaBreakType.LAST_PAGE));
p = new Paragraph()
.add("This was the story about the London lawyer "
+ "named Gabriel John Utterson who investigates strange "
+ "occurrences between his old friend, Dr. Henry Jekyll, "
+ "and the evil Edward Hyde. THE END!");
document.add(p);
document.close();
}
我需要这样的东西:
无论何时创建新的DocumentRenderer,iText都会开始返回 文档顶部–即:从首页开始。这可以让你 在同一文档上彼此相邻使用不同的渲染器 同一页。如果需要的话,我们将指示iText不要 将内容刷新到OutputStream;否则我们将无法使用 到前几页。在这种情况下,我们不需要更改任何内容 前几页。我们只想在下一个切换到另一个渲染器 页。引入到最后一页的分页符可以避免 新内容会覆盖旧内容。
答案 0 :(得分:1)
我已使用此代码:C02E08_JekyllHydeV4
我根据您的问题进行了更新:
//Initialize PDF document
PdfDocument pdf = new PdfDocument(new PdfWriter(dest));
// Initialize document
Document document = new Document(pdf);
Paragraph p = new Paragraph()
.add("Be prepared to read a story about a London lawyer "
+ "named Gabriel John Utterson who investigates strange "
+ "occurrences between his old friend, Dr. Henry Jekyll, "
+ "and the evil Edward Hyde.");
document.add(p);
document.add(new AreaBreak(AreaBreakType.NEXT_PAGE));
//Set column parameters
...
//Define column areas
...
document.setRenderer(new ColumnDocumentRenderer(document, columns));
document.add(new AreaBreak(AreaBreakType.LAST_PAGE));
// Add the full Jekyl and Hyde text
document.add(new AreaBreak(AreaBreakType.NEXT_PAGE));
document.setRenderer(new DocumentRenderer(document));
document.add(new AreaBreak(AreaBreakType.LAST_PAGE));
p = new Paragraph()
.add("This was the story about the London lawyer "
+ "named Gabriel John Utterson who investigates strange "
+ "occurrences between his old friend, Dr. Henry Jekyll, "
+ "and the evil Edward Hyde. THE END!");
document.add(p);
//Close document
document.close();
结果如下:
我认为这就是您要寻找的行为。如果不是,请说明出了什么问题。
更新:
在澄清了问题之后,很显然上述答案并不能解决问题。这是解决实际问题的方法:
我们需要创建一个自定义ParagraphRenderer
来确定Y位置:
类MyParagraphRenderer扩展了ParagraphRenderer {
float y;
public MyParagraphRenderer(Paragraph modelElement) {
super(modelElement);
}
@Override
public void drawBorder(DrawContext drawContext) {
super.drawBorder(drawContext);
y = getOccupiedAreaBBox().getBottom();
}
public float getY() {
return y;
}
}
添加第一段时,我们需要使用以下自定义ParagraphRenderer
:
Paragraph p = new Paragraph()
.add("Be prepared to read a story about a London lawyer "
+ "named Gabriel John Utterson who investigates strange "
+ "occurrences between his old friend, Dr. Henry Jekyll, "
+ "and the evil Edward Hyde.");
MyParagraphRenderer renderer = new MyParagraphRenderer(p);
p.setNextRenderer(renderer);
document.add(p);
我们现在可以像这样获得所需的Y位置:renderer.getY()
;我们使用这个Y位置来定义第一组列:
float offSet = 36;
float gutter = 23;
float columnWidth = (PageSize.A4.getWidth() - offSet * 2) / 2 - gutter;
float columnHeight1 = renderer.getY() - offSet * 2;
Rectangle[] columns1 = {
new Rectangle(offSet, offSet, columnWidth, columnHeight1),
new Rectangle(offSet + columnWidth + gutter, offSet, columnWidth, columnHeight1)};
我们可以使用这组列来创建ColumnDocumentRenderer
,但是如果需要多个页面来呈现所有内容,那么第二页上的列偏移将是错误的,因此我们也创建自定义ColumnDocumentRenderer
:
class MyColumnDocumentRenderer extends ColumnDocumentRenderer {
Rectangle[] columns2;
public MyColumnDocumentRenderer(Document document, Rectangle[] columns1, Rectangle[] columns2) {
super(document, columns1);
this.columns2 = columns2;
}
@Override
protected PageSize addNewPage(PageSize customPageSize) {
PageSize size = super.addNewPage(customPageSize);
columns = columns2;
return size;
}
}
此ColumnDocumentRenderer
接受两组列,第一页将使用一组,随后的所有页将使用第二组。这就是我们定义和应用自定义ColumnDocumentRenderer
的方式:
float columnHeight2 = PageSize.A4.getHeight() - offSet * 2;
Rectangle[] columns2 = {
new Rectangle(offSet, offSet, columnWidth, columnHeight2),
new Rectangle(offSet + columnWidth + gutter, offSet, columnWidth, columnHeight2)};
document.setRenderer(new MyColumnDocumentRenderer(document, columns1, columns2));
现在结果如下:
根据所需的第一个页面范围的段落与列中的后续内容之间的距离,可以调整renderer.getY() - offSet * 2
的值。