Java 在同一页面中的ColumnDocumentRenderer和DocumentRenderer之间切换?
我用iText7测试了一些东西,我有一个场景,我需要在顶部有DocumentRenderer段落,然后在同一页面上用它下面的两列启动ColumnDocumentRender。我遇到的问题是,当我更改同一页面上的内容时,它会将DocumentRenderer中的内容与ColumnDocumentRenderer中的内容重叠。我相信这是因为一个渲染器不知道另一个渲染器,内容从页面顶部开始。我照做了,但它只显示了如何将内容添加到下一页。它确实说 我们必须指示iText不要将内容刷新到 输出流 但有谁能告诉我我们如何才能做到这一点Java 在同一页面中的ColumnDocumentRenderer和DocumentRenderer之间切换?,java,pdf,itext,renderer,itext7,Java,Pdf,Itext,Renderer,Itext7,我用iText7测试了一些东西,我有一个场景,我需要在顶部有DocumentRenderer段落,然后在同一页面上用它下面的两列启动ColumnDocumentRender。我遇到的问题是,当我更改同一页面上的内容时,它会将DocumentRenderer中的内容与ColumnDocumentRenderer中的内容重叠。我相信这是因为一个渲染器不知道另一个渲染器,内容从页面顶部开始。我照做了,但它只显示了如何将内容添加到下一页。它确实说 我们必须指示iText不要将内容刷新到 输出流 但有谁能
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;否则我们将无法访问
转到前几页。在这种情况下,我们不需要在上更改任何内容
前几页。我们只想切换到下一个渲染器上的另一个渲染器
页引入到最后一页的分页符可以避免
新内容将覆盖旧内容
我采取了以下措施:
我根据你的问题更新了它:
//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();
结果如下所示:
我想这就是你想要的行为。如果不是,请说明出了什么问题
更新:
在澄清问题后,很明显,上述答案并不能解决问题。这就是实际问题的解决方案:
我们需要创建一个自定义的段落渲染器
,以确定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;
}
}
当我们添加第一段时,我们需要使用此自定义的段落渲染器
:
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);
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;
}
}
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));
我们现在可以像这样获得所需的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
:
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);
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;
}
}
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));
此ColumnDocumentRenderer
接受两组列,第一组列将用于第一页,第二组列将用于所有后续页。这就是我们定义和应用自定义ColumnDocumentRenderer
的方式:
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);
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;
}
}
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
我现在考虑的一个解决方案是使用ColumnDocumentRenderer,在顶部将列号设置为1,然后在底部将列号设置为2。我不知道这是否有帮助,但只是考虑是否有可能。我尝试重现您的问题,但要么我误解了问题,要么我无法重现问题问题。请对我的答案发表评论。@BrunoLowagie我能找到什么解决方案吗?MultiColumnText为旧版本的iText提供了窍门。谢谢你Bruno的帮助!:)我只是想知道这是对库本身现在实现的限制吗?还是可行的?可行的,但我现在没有时间回答。部分原因是解决方法可以在这里找到:嗯,你说的是,只要我添加段落,得到光标指针的x,y坐标,然后添加从该坐标开始的列?这非常有用。谢谢。我认为添加此解决方案也很好。这对像我这样的人会有很大帮助。再次感谢!