在同一页面的ColumnDocumentRenderer和DocumentRenderer之间切换?

时间:2018-06-28 13:53:24

标签: java pdf itext renderer itext7

我正在用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();
}

我需要这样的东西:

iText7 Columns

  

无论何时创建新的DocumentRenderer,iText都会开始返回   文档顶部–即:从首页开始。这可以让你   在同一文档上彼此相邻使用不同的渲染器   同一页。如果需要的话,我们将指示iText不要   将内容刷新到OutputStream;否则我们将无法使用   到前几页。在这种情况下,我们不需要更改任何内容   前几页。我们只想在下一个切换到另一个渲染器   页。引入到最​​后一页的分页符可以避免   新内容会覆盖旧内容。

1 个答案:

答案 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();

结果如下:

enter image description here

enter image description here

enter image description here

我认为这就是您要寻找的行为。如果不是,请说明出了什么问题。

更新:

在澄清了问题之后,很显然上述答案并不能解决问题。这是解决实际问题的方法:

我们需要创建一个自定义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));  

现在结果如下:

enter image description here

根据所需的第一个页面范围的段落与列中的后续内容之间的距离,可以调整renderer.getY() - offSet * 2的值。