首页 > 解决方案 > iText:用图像设置表格单元格的高度

问题描述

我用 iText 5.5.13.2(最新的 iText5 版本)创建了一个表格,并用从同一台 PC 上的特定文件夹读取的文本和图像填充它:

Paragraph p = new Paragraph();
p.add(new Phrase("This is a new paragraph!"));

PdfPTable table = new PdfPTable(2);
table.setWidthPercentage(100);

for(int i=0;i<imageArr.size();i++) { //imageArr.size()%2==0!
    PdfPCell cell = new PdfPCell();
    String name = imageArr.get(i);
    String path = imgFolder + File.separator + name;
    File f = new File(path);

    if(f.isFile()) {
        Image img = Image.getInstance(path);
        //cell.setCalculatedHeight(50);
        cell.addElement(img);
    } else {
        cell.addElement(new Phrase(name));
    }

    cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
    cell.setHorizontalAlignment(Element.ALIGN_MIDDLE);
    //cell.setCalculatedHeight(50);
    table.addCell(cell);
}

p.add(table);
doc.add(p);

表中的两列都使用相同的宽度(这很棒),并且大图像会自动调整大小以适应宽度(这也很棒),唯一不起作用的:

单元格都应具有一定的高度,并且大图像应相应调整大小(同时仍保持适当的高度/宽度比)。在将图像添加到单元格之前或之后使用似乎并不重要setCalculatedHeight(只做一个或另一个,参见上面的代码),单元格总是根据图像的高度设置它的高度,所以只有文本的行或横向格式的图像总是小于纵向格式的图像行。

img.setScaleToFitLineWhenOverflow(false)即使在使用and时,小图像也会调整大小(拉伸),img.setScaleToFitHeight(false)但即使这样,高度也没有正确设置。

我已经尝试使用Chunk( cell.addElement(new Chunk(img, 0, 0))) 但是图像很小,我的高度设置仍然被忽略。

如何设置单元格的高度并使图像相应地调整大小?

标签: javaitext

解决方案


我设法找到了解决方案。涉及大量测试,即使现在我也不能 100% 确定为什么它的行为方式大部分时间都是如此。

首先:不要添加元素,addElement因为一旦你用 a 调用它PdfPCell,iText 从“文本模式”(似乎也影响图像)切换到“复合模式”,从那时起忽略所有对齐,...设置对于该单元格,包括文本的水平对齐 - 您可以在此处找到原始 iText 开发人员的更详细说明(此处提供示例)。而是对第一个做任何你想做的事情,然后才用那个图像创建。之后可以编辑单元格 -但是使用 将不起作用,对它的更改不会对使用下面的代码创建的单元格产生任何影响。ImagePdfPCelltable.getDefaultCell()

我的工作代码:

float docWidth = doc.getPageSize().getWidth() - doc.leftMargin() - doc.rightMargin();
float docHeight = doc.getPageSize().getHeight() - doc.topMargin() - doc.bottomMargin();
float docWidthDiv2 = docWidth/2 - 10;
float docHeightDiv2 = docHeight/2 - 10;
PdfPCell cell = null;

if(f.isFile()) {
    Image img = Image.getInstance(path);
    //img.scaleAbsolute(100, 50);

    if(img.getWidth() < docWidthDiv2 && img.getHeight < docHeightDiv2) {
        cell = new PdfPCell(img, false);
    } else {
        cell = new PdfPCell(img, true);
    }
} else {
    cell = new PdfPCell(new Phrase(name));
}

cell.setFixedHeight(50); //"setCalculatedHeight" doesn't work

为什么我将图像的宽度docWidthDiv2与图像的高度进行比较docHeightDiv2

有很多组合可以设置单元格的高度,但没有一个显示出我预期的 100% 的行为:应该缩小真正大的图像以适应列的宽度(对于横向模式下的图像更重要),但也要尊重单元格的固定高度(对于纵向模式的图像更重要),同时仍保持其纵横比。已经舒适地适合单元格的小图像根本不应该缩放。

的文档new PDfPCell(Image image, boolean fit)描述了fit参数:

true使图像适合单元格

在我的情况下true,调整图像的大小(同时仍然尊重其纵横比和单元格的高度),直到它接触到单元格的两个相对侧,因此:大图像的尺寸减小,小图像被拉伸。

图像的纵横比和false单元格的高度仍然受到尊重,但是虽然小图像保持其大小,但横向模式下的大图像会“渗入”相邻单元格(并且setScaleToFitLineWhenOverflow没有帮助),而纵向模式下的大图像甚至可能不会完全显示(当它们对单元格来说太高时)。

为了不拉伸小图像但减小大图像的大小,需要将两者结合起来。我只添加了-10,因此潜在的默认填充不会弄乱它。如果你想在表格之前或之后添加文本,那么你也必须从中扣除它的高度docHeightDiv2

如前所述,我还测试了其他组合,我从中获得了最重要的信息:

如果在添加图像之前设置了单元格的高度,那么无论它比单元格小(单元格高度缩小)还是更大(单元格高度增加),图像都会覆盖高度。

在参数之间可以使用几种组合,设置图像大小和设置单元格的高度,但其中大多数图像要么保持其原始大小(例如 2000x1000 不会在页面上完全可见),要么它们的尺寸会增加,直到它们接触到单元格的两个相对侧(这也增加了单元格的高度)。最后只剩下一个组合仍然有用(在我看来) - 一个例子:

img.scaleAbsolute(100, 50);
cell = new PdfPCell(img, false);
cell.setVerticalAlignment(Element.ALIGN_MIDDLE); //"center" doesn't work here
cell.setHorizontalAlignment(Element.ALIGN_CENTER); //"middle" doesn't work here
cell.setFixedHeight(150);

这将在 150 个单位高的单元格中心创建一个大小为 100x50(忽略原始纵横比)的图像(= 图像上方和下方 50 个单位的填充)。

关于 iText 表格的附加信息:

列平等地共享表格的可用宽度,并且无需更改它,即使第一个单元格包含一个非常小的图像而第二个单元格包含一个非常大的图像。在这方面,您唯一需要注意的是添加的单元格的数量 - 行始终必须完全填充,因此具有 3 列的表每行必须包含 3 个单元格,否则该行获胜' 不会打印到 pdf 文件中(同样也不会打印空的新页面)。可以创建空的额外单元格来填充行的其余部分:

PdfPCell extra = new PdfPCell();
extra.setFixedHeight(50);
table.addCell(extra);

推荐阅读