2017-08-30 91 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); 
     } 

    } 

} `