在iText7中,有没有类似iText5的calculateHeights方法的方法?
In iText7, is there a way like iText5's calculateHeights method?
在iText5中,我们可以在需要的时候获取PdfPTable的高度"public float calculateHeights(boolean firsttime)"。
但是在 iText7 中,我们如何获取当前的 table 高度值(尤其是在将 table 添加到其父元素之前)?
我已经测试了 "table.getHeight()" 方法,但它 returns 无效。
而且我还发现在一个 table 渲染对象中我可以得到这个值,但是限制是渲染需要在 table 添加到它的父元素时被触发,所以时间不是我的需要。
因为有时我们需要这个值来计算来决定"y-axis"值。
嗯,由于在 iText7 中编写渲染器框架的方式,(目前)还没有办法在将布局对象添加到父文档之前计算它的高度,因为实际计算布局对象的高度发生在将它们添加到 a Document
对象时。
但是您可以重新布局 Document
,从而允许您更改之前添加的元素的内容。使用它,您可以模拟 tables 的渲染并在添加新元素时掌握它们的高度。 table.getHeight()
仍然不起作用,因为它检索高度 属性,并且 属性 当前未在 table 渲染过程中的任何位置设置。
在下面的示例中,我编写了一个方便的方法来遍历 renderer-tree 并打印出每个 table 在文档中占据的区域,以向您展示如何获得计算的高度。
示例本身向文档添加了一些 tables,显示了占用的区域,向每个 table 添加了一些单元格,显示了占用的区域(自从添加到之前已经添加的元素不触发布局),最后手动触发重布局显示最终占用的区域。
public class DelayedLayout {
public static String DEST = "target/output/Whosebug/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);
}
}
在 iText5 中,元素和有关它们 position/size 的信息有点混合在一起,这允许您在 PdfPTable
元素上调用 calculateWidths
。
在 iText7 中,此功能是分开的,这允许 rendering/layouting 元素具有不同类型的灵活性。
因此,以 Table
实例为例的模型元素不知道它们的位置或大小。并且调用 table.getHeight
结果为 null
因为 table
之前没有设置 HEIGHT
属性。
要计算 table 高度,必须使用渲染功能。
对于模型元素,您可以获得表示该模型元素及其所有子元素的渲染器子树,并且 layout
它在任何给定区域中。要真正知道 table 的高度,您需要创建一个区域,该区域有意识地足以放置元素的全部内容。
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。请注意,如果无法将 table 放置到该高度,则结果将永远不会超过此给定高度,因此对于您的用例来说它是不正确的(知道 table 的总高度)。因此,请确保通过足以放置整个 table.
的高度
.setParent(doc.getRenderer())
部分在这里很重要,用于检索继承属性。请注意,我们没有为 table
元素设置很多属性,甚至字体,但此信息对于了解此元素将占据的区域至关重要。所以这个信息会在layout
期间从父链继承。您可以通过更改文档的字体:document.setFont(newFont);
或字体大小:document.setFontSize(24);
并观察由此产生的高度变化来测试这一点
在iText5中,我们可以在需要的时候获取PdfPTable的高度"public float calculateHeights(boolean firsttime)"。
但是在 iText7 中,我们如何获取当前的 table 高度值(尤其是在将 table 添加到其父元素之前)?
我已经测试了 "table.getHeight()" 方法,但它 returns 无效。 而且我还发现在一个 table 渲染对象中我可以得到这个值,但是限制是渲染需要在 table 添加到它的父元素时被触发,所以时间不是我的需要。
因为有时我们需要这个值来计算来决定"y-axis"值。
嗯,由于在 iText7 中编写渲染器框架的方式,(目前)还没有办法在将布局对象添加到父文档之前计算它的高度,因为实际计算布局对象的高度发生在将它们添加到 a Document
对象时。
但是您可以重新布局 Document
,从而允许您更改之前添加的元素的内容。使用它,您可以模拟 tables 的渲染并在添加新元素时掌握它们的高度。 table.getHeight()
仍然不起作用,因为它检索高度 属性,并且 属性 当前未在 table 渲染过程中的任何位置设置。
在下面的示例中,我编写了一个方便的方法来遍历 renderer-tree 并打印出每个 table 在文档中占据的区域,以向您展示如何获得计算的高度。
示例本身向文档添加了一些 tables,显示了占用的区域,向每个 table 添加了一些单元格,显示了占用的区域(自从添加到之前已经添加的元素不触发布局),最后手动触发重布局显示最终占用的区域。
public class DelayedLayout {
public static String DEST = "target/output/Whosebug/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);
}
}
在 iText5 中,元素和有关它们 position/size 的信息有点混合在一起,这允许您在 PdfPTable
元素上调用 calculateWidths
。
在 iText7 中,此功能是分开的,这允许 rendering/layouting 元素具有不同类型的灵活性。
因此,以 Table
实例为例的模型元素不知道它们的位置或大小。并且调用 table.getHeight
结果为 null
因为 table
之前没有设置 HEIGHT
属性。
要计算 table 高度,必须使用渲染功能。
对于模型元素,您可以获得表示该模型元素及其所有子元素的渲染器子树,并且 layout
它在任何给定区域中。要真正知道 table 的高度,您需要创建一个区域,该区域有意识地足以放置元素的全部内容。
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。请注意,如果无法将 table 放置到该高度,则结果将永远不会超过此给定高度,因此对于您的用例来说它是不正确的(知道 table 的总高度)。因此,请确保通过足以放置整个 table. 的高度
.setParent(doc.getRenderer())
部分在这里很重要,用于检索继承属性。请注意,我们没有为table
元素设置很多属性,甚至字体,但此信息对于了解此元素将占据的区域至关重要。所以这个信息会在layout
期间从父链继承。您可以通过更改文档的字体:document.setFont(newFont);
或字体大小:document.setFontSize(24);
并观察由此产生的高度变化来测试这一点