【问题标题】:Switch between ColumnDocumentRenderer and DocumentRenderer in same page?在同一页面中的 ColumnDocumentRenderer 和 DocumentRenderer 之间切换?
【发布时间】:2018-12-07 15:27:04
【问题描述】:

我用 iText7 测试了一些东西,我有一个场景,我需要在顶部有 DocumentRenderer 段落,然后在同一页面上启动 ColumnDocumentRender 并在其正下方有 2 列。我遇到的问题是,当我更改同一页面上的内容时,它会将 DocumentRenderer 中的内容与 ColumnDocumentRenderer 中的内容重叠。我相信这是因为一个渲染器不知道另一个渲染器,并且内容从页面顶部开始。我关注了this tutorial,但它只显示了如何将内容添加到下一页。它确实说

我们必须指示 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();
}

我需要这样的东西:

iText7 Columns

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

【问题讨论】:

  • 我现在正在考虑的一个解决方案是在整个过程中使用 ColumnDocumentRenderer 并将列号设置为顶部的 1,然后将列号设置为底部的 2。我不知道这是否会有所帮助,但只是考虑是否可能。
  • 我尝试重现您的问题,但要么我误解了问题,要么我无法重现问题。请评论我的回答。
  • @BrunoLowagie 有什么我可以研究的解决方案吗? MultiColumnText 为旧版本的 iText 做到了这一点。 i.stack.imgur.com/s53A0.png

标签: java pdf itext renderer itext7


【解决方案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 的值。

【讨论】:

  • 感谢布鲁诺的所有帮助! :)
  • 只是想知道现在实现this 是否对库本身有限制?还是可行?
  • 可行,但我现在没时间回答。部分解决方案可以在这里找到:developers.itextpdf.com/content/…
  • hmm 所以你的意思是我添加段落后,获取光标指针的 x、y 坐标,然后添加从该坐标开始的列?
  • 这很有帮助。谢谢你。我认为将此解决方案也添加到developers.itextpdf.com/content/itext-7-building-blocks/… 会很好。对像我这样的人会有很大帮助。再次感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-22
  • 2016-08-04
  • 2018-09-13
  • 2019-08-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多