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);
}
}


Что я делаю не так?

455   2  

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

    Ничего не найдено.