Itext7 CellRenderer работает не всегда
Я использую Itext7 для создания pdf-файла с таблицей в нем.
Таблица занимает несколько страниц.
Я также переопределяю средство визуализации ячеек, чтобы добавить поле формы в некоторую ячейку.
Я заметил, что когда таблица переходит на новую страницу, первая строка не вызывает метод draw класса CellRender.
Я поместил немного кода ниже для лучшего понимания.
...
//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);
}
}
Что я делаю не так?
2 ответов:
Если вы переходите на новую страницу, то ваш
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); }
Вы не переопределяете один очень важный метод:
public IRenderer getNextRenderer().Если ячейка не может быть помещена на страницу, iText создает ячейку переполнения (см. Метод
protected AbstractRenderer createOverflowRenderer(int layoutResult). Если вы не переопределитеgetNextRenderer, iText по умолчанию создаст простой CellRenderer, используя его getModelElement ().Поэтому я предлагаю вам добавить 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); } }} '
Comments