在同一页面中切换ColumnDocumentRenderer和DocumentRenderer? [英] Switch between ColumnDocumentRenderer and DocumentRenderer in same page?

查看:192
本文介绍了在同一页面中切换ColumnDocumentRenderer和DocumentRenderer?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我用iText7测试了一些东西,我有一个场景,我需要在顶部放置DocumentRenderer段落,然后在同一页面上的正下方启动ColumnDocumentRender。我遇到的问题是当我更改同一页面上的内容时,它与DocumentRenderer中的内容与ColumnDocumentRenderer中的内容重叠。我相信这是因为一个渲染器不知道其他渲染,内容从页面顶部开始。我按照







我认为这是您正在寻找的行为。如果不是,请解释出现了什么问题。



更新:



之后澄清问题,很明显上述答案并没有解决问题。这是实际问题的解决方案:



我们需要创建一个自定义 ParagraphRenderer 来确定Y位置:
class MyParagraphRenderer扩展ParagraphRenderer {

  float y; 

public MyParagraphRenderer(Paragraph modelElement){
super(modelElement);
}

@Override
public void drawBorder(DrawContext drawContext){
super.drawBorder(drawContext);
y = getOc​​cupiedAreaBBox()。getBottom();
}

public float getY(){
return y;
}

}

当我们添加第一段时,我们需要使用这个自定义 ParagraphRenderer

 段落p =新段落()
.add(准备读一篇关于伦敦律师的故事
+名叫Gabriel John Utterson,调查他的老朋友亨利博士之间发生的奇怪的
+事件杰基尔,
+和邪恶的爱德华海德。);
MyParagraphRenderer renderer = new MyParagraphRenderer(p);
p.setNextRenderer(渲染器);
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;
返回大小;
}
}

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 的值。


I was testing few things with iText7 and I have a scenario where I need to have DocumentRenderer paragraph at the top and then start the ColumnDocumentRender with 2 columns right below it on the same page. The problem I am having is when I change the content on same page it overlaps content from DocumentRenderer with content from ColumnDocumentRenderer. I believe it is because one render does not know about the other render and contents starts from the top of the page. I followed this tutorial but it only shows how to add content to the next page. It does say

we'll have to instruct iText not to flush the content to the OutputStream

But can anyone show me exactly how we can achieve this?

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();
}

I need something like this:

iText7 Columns

Whenever you create a new DocumentRenderer, iText starts returns to the top of the document –that is: from the first page. This allows you to use different renderers on the same document next to each other on the same page. If that is needed, we'll have to instruct iText not to flush the content to the OutputStream; otherwise we won't have access to previous pages. In this case, we don't need to change anything on previous pages. We just want to switch to another renderer on the next page. Introducing a page break that goes to the last page will avoid that new content overwrites old content.

解决方案

I have taken this code: C02E08_JekyllHydeV4

And I updated it according to what you have in your question:

//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();

The result looks like this:

I think that's the behavior you are looking for. If it's not, please explain what goes wrong.

UPDATE:

After clarifying the question, it is clear that the above answer doesn't solve the problem. This is the solution to the actual problem:

We need to create a custom ParagraphRenderer to determine a Y-position: class MyParagraphRenderer extends 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;
    }

}

When we add the first paragraph, we need to use this custom 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);

We can now get the Y position we need like this: renderer.getY(); we use this Y position to define a first set of columns:

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)};

We could use this set of columns to create a ColumnDocumentRenderer, but if more than one page is needed to render all the content, then the offset of the columns on the second page will be wrong, hence we also create a custom 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;
    }
}

This ColumnDocumentRenderer accepts two sets of columns, one set will be used on the first page, the second set will be used on all subsequent pages. This is how we define and apply the custom 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));  

Now the result looks like this:

Depending on the distance you want between the first page-wide paragraph and the subsequent content in the columns, you can adjust the value of renderer.getY() - offSet * 2.

这篇关于在同一页面中切换ColumnDocumentRenderer和DocumentRenderer?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆