Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/apache-flex/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在同一页面中的ColumnDocumentRenderer和DocumentRenderer之间切换?_Java_Pdf_Itext_Renderer_Itext7 - Fatal编程技术网

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

Java 在同一页面中的ColumnDocumentRenderer和DocumentRenderer之间切换?,java,pdf,itext,renderer,itext7,Java,Pdf,Itext,Renderer,Itext7,我用iText7测试了一些东西,我有一个场景,我需要在顶部有DocumentRenderer段落,然后在同一页面上用它下面的两列启动ColumnDocumentRender。我遇到的问题是,当我更改同一页面上的内容时,它会将DocumentRenderer中的内容与ColumnDocumentRenderer中的内容重叠。我相信这是因为一个渲染器不知道另一个渲染器,内容从页面顶部开始。我照做了,但它只显示了如何将内容添加到下一页。它确实说 我们必须指示iText不要将内容刷新到 输出流 但有谁能

我用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坐标,然后添加从该坐标开始的列?这非常有用。谢谢。我认为添加此解决方案也很好。这对像我这样的人会有很大帮助。再次感谢!