2017-08-30 68 views
3

我正在使用Itext7创建一个带有表格的pdf。
该表格占用多个页面。
我也重写了单元格渲染器以将某个表单添加到某个单元格。
我注意到,当表进入一个新页面时,第一行不会触发CellRender类的绘制方法。
为了更好的理解,我在下面放了一些代码。Itext7 CellRenderer并不总是工作

... 
//adding the cells to table 
for (int i = 0; i < 10; i++) { 
    addRow(table,i); 
} 
... 
//addRow implementation 
private void addRow(Table table, int row) throws IOException { 
    table.startNewRow(); 

    PdfFont zapfdingbats = PdfFontFactory.createFont(FontConstants.ZAPFDINGBATS); 

    Cell checkBoxCell = new Cell().add(new Paragraph("o").setFont(zapfdingbats).setMargins(9, 0, 0, 11)).setKeepTogether(true); 
    checkBoxCell.setNextRenderer(new CheckboxCellRenderer(checkBoxCell, "cb"+row)); 
    table.addCell(checkBoxCell); 
    ... 
    //other cells here 
} 
... 
//The implementation of the custom CellRender 
protected class CheckboxCellRenderer extends CellRenderer { 
    protected String name; 

    public CheckboxCellRenderer(Cell modelElement, String name) { 
     super(modelElement); 
     this.name = name; 
    } 
    //this method is not triggered for the first row when a new page is created 
    @Override 
    public void draw(DrawContext drawContext) { 
     System.out.println(name); 
     super.draw(drawContext); 
     float x = getOccupiedAreaBBox().getLeft(); 
     float y = getOccupiedAreaBBox().getBottom(); 
     float width = getOccupiedAreaBBox().getRight()-getOccupiedAreaBBox().getLeft(); 
     float height = getOccupiedAreaBBox().getTop()-getOccupiedAreaBBox().getBottom(); 
     Rectangle rect = new Rectangle(x+5, y+5, width-10, height-10); 
     PdfTextFormField pdfTextFormField = PdfFormField.createText(drawContext.getDocument(), rect, name); 
     PdfAcroForm.getAcroForm(drawContext.getDocument(), true).addField(pdfTextFormField); 
    } 
} 

我在做什么错?

回答

5

如果转到新页面,则会丢弃Renderer并创建新的Renderer对象。这样做是为了避免在模型对象发生变化的情况下混淆状态。在这种情况下,该方法getNextRenderer叫做:

/** 
* Gets a new instance of this class to be used as a next renderer, after this renderer is used, if 
* {@link #layout(LayoutContext)} is called more than once. 
* @return new renderer instance 
*/ 
IRenderer getNextRenderer(); 

所以,你应该确定,如果你只是重写此方法在自定义CheckboxCellRenderer类:

@Override 
public IRenderer getNextRenderer() { 
    return new CheckboxCellRenderer(getModelElement(), name); 
} 
5

不重写一个很重要的方法: public IRenderer getNextRenderer()

如果电池不能放在一个页面上,iText的创建溢出细胞(见protected AbstractRenderer createOverflowRenderer(int layoutResult)方法。如果你没有覆盖getNextRenderer iText的默认情况下会使用其getModelElement()。

所以我建议创建简单的CellRenderer你应该增加summat: @Override public IRenderer getNextRenderer() { return new CheckboxCellRenderer(getModelElement(), name); }

我用你的代码创建的下一个样本和它的作品如您所愿 `

public class ArrayToTable extends GenericTest { 
public static final String DEST = "./target/test/resources/sandbox/tables/array_to_table.pdf"; 

public static void main(String[] args) throws Exception { 
    File file = new File(DEST); 
    file.getParentFile().mkdirs(); 
    new CustomRendererTest().manipulatePdf(DEST); 
} 

@Override 
protected void manipulatePdf(String dest) throws Exception { 
    PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest)); 
    Document doc = new Document(pdfDoc); 

    Table table = new Table(1); 
    //adding the cells to table 
    for (int i = 0; i < 25; i++) { 
     addRow(table, i); 
    } 

    doc.add(table); 
    doc.close(); 
} 

    //addRow implementation 
    private void addRow(Table table, int row) throws IOException { 
     table.startNewRow(); 

     PdfFont zapfdingbats = PdfFontFactory.createFont(FontConstants.ZAPFDINGBATS); 

     Cell checkBoxCell = new Cell().add(new Paragraph("o").setFont(zapfdingbats).setMargins(9, 0, 0, 11)).setKeepTogether(true); 
     checkBoxCell.setNextRenderer(new CheckboxCellRenderer(checkBoxCell, "cb"+row)); 
     table.addCell(checkBoxCell); 
     //other cells here 
    } 

    //The implementation of the custom CellRender 
    protected class CheckboxCellRenderer extends CellRenderer { 
     protected String name; 

     public CheckboxCellRenderer(Cell modelElement, String name) { 
      super(modelElement); 
      this.name = name; 
     } 
     //this method is not triggered for the first row when a new page is created 
     @Override 
     public void draw(DrawContext drawContext) { 
      System.out.println(name); 
      super.draw(drawContext); 
      float x = getOccupiedAreaBBox().getLeft(); 
      float y = getOccupiedAreaBBox().getBottom(); 
      float width = getOccupiedAreaBBox().getRight()-getOccupiedAreaBBox().getLeft(); 
      float height = getOccupiedAreaBBox().getTop()-getOccupiedAreaBBox().getBottom(); 
      Rectangle rect = new Rectangle(x+5, y+5, width-10, height-10); 
      PdfTextFormField pdfTextFormField = PdfFormField.createText(drawContext.getDocument(), rect, name); 
      PdfAcroForm.getAcroForm(drawContext.getDocument(), true).addField(pdfTextFormField); 
     } 

     @Override 
     public IRenderer getNextRenderer() { 
      return new CheckboxCellRenderer(getModelElement(), name); 
     } 

    } 

} `