在itext7中,是否有类似itext5的calculateheights方法的方法?

xytpbqjk  于 2021-07-06  发布在  Java
关注(0)|答案(2)|浏览(656)

在itext5中,我们可以在需要“public float calculateheights(boolean firsttime)”时获得pdfptable的高度。
但是在itext7中,如何获得当前表的高度值(尤其是在将表添加到其父元素之前)?
我已经测试了“table.getheight()”方法,但它返回null。我还发现在一个table render对象中我可以得到这个值,但是限制是当table添加到其父元素时需要触发render,所以时间不是我需要的。
因为有时我们需要这个值来计算来决定“y轴”的值。

k97glaaz

k97glaaz1#

在itext5中,元素和关于它们的位置/大小的信息混合在一起,这允许您调用 calculateWidthsPdfPTable 元素。
在itext7中,这个功能是分离的,这使得呈现/布局元素具有不同的灵活性。
因此,模型元素 Table 示例就是一个例子,不知道自己的位置或大小。打电话来 table.getHeight 结果 null 因为 table 没有 HEIGHT 属性之前设置为。
要计算表格高度,必须使用渲染功能。
对于模型元素,可以获取表示此模型元素及其所有子元素的呈现器的子树,以及 layout 它在任何给定的区域。要真正了解一个表的高度,您需要创建一个区域,该区域在有意识的情况下足以放置元素的全部内容。

PdfDocument pdfDoc = ...
Document doc = ...

Table table = new Table(2)
            .addCell(new Cell().add(new Paragraph("cell 1, 1")))
            .addCell(new Cell().add(new Paragraph("cell 1, 2")));
LayoutResult result = table.createRendererSubTree().setParent(doc.getRenderer()).layout(
            new LayoutContext(new LayoutArea(1, new Rectangle(0, 0, 400, 1e4f))));

System.out.println(result.getOccupiedArea().getBBox().getHeight());

上面的代码打印出来了 22.982422O 对我来说,结果可能会因元素的配置和属性而异。
我想指出代码的两个重要部分:
我们通过了 1e4f 因为 LayoutArea ,考虑到这足以放置整张table。请注意,如果无法将表格放置到该高度,结果将永远不会超过此给定高度,因此它将不适合您的用例(知道表格的总高度)。因此,一定要通过高度,这将是足够的位置,整个表。 .setParent(doc.getRenderer()) 部分在这里很重要,用于检索继承属性。请注意,我们没有为 table 元素,甚至字体,但此信息对于知道此元素将占据的区域是必不可少的。因此,此信息将在运行期间从父链继承 layout . 您可以通过更改文档的字体来测试这一点: document.setFont(newFont); ,或字体大小: document.setFontSize(24); 观察由此产生的高度变化

h7appiyu

h7appiyu2#

好吧,由于渲染器框架在itext7中的编写方式,在将布局对象添加到父文档之前,还没有一种方法来计算布局对象的高度,因为实际计算布局对象的高度是在将其添加到父文档时进行的 Document 对象。
但是,您可以重新布置 Document ,允许您更改以前添加的元素的内容。使用此功能,可以模拟表的呈现,并在添加新元素时控制表的高度。这个 table.getHeight() 仍然不起作用,因为它检索height属性,并且该属性当前未在表呈现过程中的任何位置设置。
在下面的示例中,我编写了一个方便的方法,该方法迭代渲染器树并打印出文档中每个表所占的区域,向您展示如何获得计算出的高度。
该示例本身向文档中添加一些表,显示占用区域,向每个表中添加一些单元格,显示占用区域(它们是相同的,因为添加到以前添加的元素不会触发布局),最后手动触发重新布局并显示最终的占用区域。

public class DelayedLayout {
    public static String DEST = "target/output/StackOverflow/DelayedLayout/delayed.pdf";

    public static void main(String[] args)throws IOException, FileNotFoundException{
        File file = new File(DEST);
        file.getParentFile().mkdirs();
        new DelayedLayout().createPdf(DEST);
    }

    public void createPdf(String dest) throws IOException, FileNotFoundException{
        PdfWriter writer = new PdfWriter(dest);
        PdfDocument pdfDoc = new PdfDocument(writer);
        boolean immediateFlush = false;
        boolean relayout = true;
        //Set immediate layout to false, so the document doesn't immediatly write render-results to its outputstream
        Document doc = new Document(pdfDoc, PageSize.A4,immediateFlush);
        Table tOne = createSimpleTable();
        for(int i= 0; i< 5; i++) {
            //Add a table and some whitespace
            doc.add(tOne);

            doc.add(new Paragraph(""));

        }
        System.out.println("\nInitial layout results");
        printOccupiedAreasOfTableRenderers(doc.getRenderer());
        System.out.println("\nAdding extra cells to the table");
        addToTable(tOne);
        printOccupiedAreasOfTableRenderers(doc.getRenderer());
        System.out.println("\nForcing the document to redo the layout");
        if(relayout)doc.relayout();
        printOccupiedAreasOfTableRenderers(doc.getRenderer());
        doc.close();
    }

    /**
     * Create a very simple table
     * @return simple table
     */
    private Table createSimpleTable(){
        int nrOfCols = 3;
        int nrOfRows = 5;

        Table res = new Table(nrOfCols);
        for(int i= 0; i<nrOfRows;i++){
            for(int j = 0; j<nrOfCols;j++){
                Cell c = new Cell();
                c.add(new Paragraph("["+i+", "+j+"]"));
                res.addCell(c);
            }
        }

        return res;
    }

    /**
     * Add some extra cells to an exisiting table
     * @param tab table to add cells to
     */
    private void addToTable(Table tab){
        int nrOfRows = 5;
        int nrOfCols = tab.getNumberOfColumns();
        for(int i=0; i<nrOfRows*nrOfCols;i++){
            Cell c = new Cell();
            c.add(new Paragraph("Extra cell"+ i));
            tab.addCell(c);
        }

    }

    /**
     * Recursively iterate over the renderer tree, writing the occupied area to the console 
     * @param currentNode current renderer-node to check
     */
    private void printOccupiedAreasOfTableRenderers(IRenderer currentNode){
        if(currentNode.getClass().equals(TableRenderer.class)){
            System.out.println("Table renderer with occupied area: " + currentNode.getOccupiedArea());
        }
        for (IRenderer child:currentNode.getChildRenderers()) {
            printOccupiedAreasOfTableRenderers(child);
        }
    }

相关问题