Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/328.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 在itext 7中将html转换为pdf时,如何仅为某些页面获得横向方向?_Java_Itext_Landscape_Itext7_Html2pdf - Fatal编程技术网

Java 在itext 7中将html转换为pdf时,如何仅为某些页面获得横向方向?

Java 在itext 7中将html转换为pdf时,如何仅为某些页面获得横向方向?,java,itext,landscape,itext7,html2pdf,Java,Itext,Landscape,Itext7,Html2pdf,我使用pdfHTML的convertToPDF()方法,使用iText7将HTML转换为PDF。我想更改PDF文档中几个特定页面的页面方向。这些页面的内容是动态的,我们无法猜测横向中应该有多少页面(即,动态表的内容可以占用多个页面) 当前情况:我创建了一个自定义工作程序(实现ITagWorker),该工作程序对标签 自定义工作人员: public class LandscapeDivTagWorker implements ITagWorker { @Override publ

我使用pdfHTML的
convertToPDF()
方法,使用iText7将HTML转换为PDF。我想更改PDF文档中几个特定页面的页面方向。这些页面的内容是动态的,我们无法猜测横向中应该有多少页面(即,动态表的内容可以占用多个页面)

当前情况:我创建了一个自定义工作程序(实现ITagWorker),该工作程序对标签

自定义工作人员:

public class LandscapeDivTagWorker implements ITagWorker {

    @Override
    public void processEnd(IElementNode element, ProcessorContext context) {
    }

    @Override
    public boolean processContent(String content, ProcessorContext context) {
        return false;
    }

    @Override
    public boolean processTagChild(ITagWorker childTagWorker, ProcessorContext context) {
        return false;
    }

    @Override
    public IPropertyContainer getElementResult() {
        return new AreaBreak(new PageSize(PageSize.A4).rotate());
    }
}
有没有一种方法可以定义应该在横向视图中显示的所有内容

比如:

<p>Display in portrait</p>
<landscape>
<div>
<p>display in landscape</p>
…
<table>
..
</table>
</div>
</landscape>
以纵向显示

景观展示

… ..
或者使用CSS类:

<p>Display in portrait</p>
<div class="landscape">
<p>display in landscape</p>
…
<table>
..
</table>
</div>
以纵向显示

景观展示

… ..
结果=>1页纵向,另一页横向(所有div内容应为横向)


PS:我遵循这个提示,使用了一个定制的CssApplierFactory,但结果是一样的=>只不过使用横向类的第一个页面是横向的,而表格的其他内容是纵向的

做这件事实际上相当棘手,但整个机制仍有足够的灵活性来满足这一要求

我们将致力于支持以下语法:

<p>Display in portrait</p>
<landscape>
<div>
<p>display in landscape</p>
<p>content</p>
.....
<p>content</p>
</div>
</landscape>
<p> After portrait </p>
自定义标记工作程序工厂也几乎没有变化-它只是将
PdfDocument
传递给标记工作程序:

private static class CustomTagWorkerFactory extends DefaultTagWorkerFactory {
    PdfDocument pdfDocument;

    public CustomTagWorkerFactory(PdfDocument pdfDocument) {
        this.pdfDocument = pdfDocument;
    }

    @Override
    public ITagWorker getCustomTagWorker(IElementNode tag, ProcessorContext context) {
        if ("landscape".equalsIgnoreCase(tag.name())) {
            return new LandscapeDivTagWorker(tag, context, pdfDocument);
        }
        return null;
    }
}
LandscapeDivTagWorker
的思想是创建一个
Div
包装器,将
标记的内部内容放在那里,但也用
AreaBreak
元素将其包围-前一个将强制使用横向方向的新分页符,并更改整个文档的默认页面大小,同时接下来的一个将恢复所有内容-强制拆分为纵向页面大小,并将默认页面大小设置为纵向。请注意,我们还使用
setNextRenderer
AreaBreak
设置一个自定义呈现程序,以实际设置该中断时的默认页面大小:

private static class LandscapeDivTagWorker extends DivTagWorker {
    private PdfDocument pdfDocument;

    public LandscapeDivTagWorker(IElementNode element, ProcessorContext context, PdfDocument pdfDocument) {
        super(element, context);
        this.pdfDocument = pdfDocument;
    }

    @Override
    public IPropertyContainer getElementResult() {
        IPropertyContainer baseElementResult = super.getElementResult();
        if (baseElementResult instanceof Div) {
            Div div = new Div();
            AreaBreak landscapeAreaBreak = new AreaBreak(new PageSize(PageSize.A4).rotate());
            landscapeAreaBreak.setNextRenderer(new DefaultPageSizeChangingAreaBreakRenderer(landscapeAreaBreak, pdfDocument));
            div.add(landscapeAreaBreak);
            div.add((IBlockElement) baseElementResult);
            AreaBreak portraitAreaBreak = new AreaBreak(new PageSize(PageSize.A4));
            portraitAreaBreak.setNextRenderer(new DefaultPageSizeChangingAreaBreakRenderer(portraitAreaBreak, pdfDocument));
            div.add(portraitAreaBreak);
            baseElementResult = div;
        }
        return baseElementResult;
    }
}
自定义区域分隔符渲染器的实现非常简单-我们仅将默认页面大小设置为
PdfDocument
-其余部分在默认实现下完成,我们从以下扩展:

private static class DefaultPageSizeChangingAreaBreakRenderer extends AreaBreakRenderer {
    private PdfDocument pdfDocument;
    private AreaBreak areaBreak;

    public DefaultPageSizeChangingAreaBreakRenderer(AreaBreak areaBreak, PdfDocument pdfDocument) {
        super(areaBreak);
        this.pdfDocument = pdfDocument;
        this.areaBreak = areaBreak;
    }

    @Override
    public LayoutResult layout(LayoutContext layoutContext) {
        pdfDocument.setDefaultPageSize(areaBreak.getPageSize());
        return super.layout(layoutContext);
    }
}
因此,您将获得与屏幕截图上类似的页面设置:


非常感谢您的回复,它工作得很好:)但是,当我尝试转换包含另一个带有横向标记的模板时(如
),我在将元素添加到文档中时遇到了一个循环(包含横向标记的元素有问题)调试后,我在第二个for循环的RootRenderer类的addChild方法中找到了该循环。你知道吗?我通过删除一个CSS类修复了这个问题,该类包含以下样式
分页符:avoid
private static class LandscapeDivTagWorker extends DivTagWorker {
    private PdfDocument pdfDocument;

    public LandscapeDivTagWorker(IElementNode element, ProcessorContext context, PdfDocument pdfDocument) {
        super(element, context);
        this.pdfDocument = pdfDocument;
    }

    @Override
    public IPropertyContainer getElementResult() {
        IPropertyContainer baseElementResult = super.getElementResult();
        if (baseElementResult instanceof Div) {
            Div div = new Div();
            AreaBreak landscapeAreaBreak = new AreaBreak(new PageSize(PageSize.A4).rotate());
            landscapeAreaBreak.setNextRenderer(new DefaultPageSizeChangingAreaBreakRenderer(landscapeAreaBreak, pdfDocument));
            div.add(landscapeAreaBreak);
            div.add((IBlockElement) baseElementResult);
            AreaBreak portraitAreaBreak = new AreaBreak(new PageSize(PageSize.A4));
            portraitAreaBreak.setNextRenderer(new DefaultPageSizeChangingAreaBreakRenderer(portraitAreaBreak, pdfDocument));
            div.add(portraitAreaBreak);
            baseElementResult = div;
        }
        return baseElementResult;
    }
}
private static class DefaultPageSizeChangingAreaBreakRenderer extends AreaBreakRenderer {
    private PdfDocument pdfDocument;
    private AreaBreak areaBreak;

    public DefaultPageSizeChangingAreaBreakRenderer(AreaBreak areaBreak, PdfDocument pdfDocument) {
        super(areaBreak);
        this.pdfDocument = pdfDocument;
        this.areaBreak = areaBreak;
    }

    @Override
    public LayoutResult layout(LayoutContext layoutContext) {
        pdfDocument.setDefaultPageSize(areaBreak.getPageSize());
        return super.layout(layoutContext);
    }
}