Прежде всего, нам нужно правильно переопределить рендерер, т.е. переопределить метод getNextRenderer()
.В настоящее время TableRenderer
довольно проблематично переопределить, потому что безпараметрический конструктор TableRenderer
недоступен, а другие конструкторы выполняют неявную работу, которая изменяет состояние.Но мы все еще можем обойти эту проблему с помощью следующего кода:
@Override
public IRenderer getNextRenderer() {
CustomTableRenderer nextTable = new CustomTableRenderer((Table) modelElement);
nextTable.rows.clear();
nextTable.rowRange = null;
return nextTable;
}
Отказ от ответственности : поскольку в ответе используются частные детали реализации TableRenderer
, он может не сработать в будущем.Он работает с 7.1.6
, который является последней выпущенной версией на момент написания этого поста.Вы должны создать собственный форк кода для таких целей. Также приветствуются запросы извлечения .
Если мы посмотрим на реализацию TableRenderer
, то увидим, что класс содержит heights
( строка в коде ) иcountedColumnWidth
( строка в коде ) поля, которые звучат интересно, но они private
.Это означает, что мы должны создать наш собственный форк iText (исходный код доступен по https://github.com/itext/itext7),, сделать эти поля protected
и использовать их в нашем подклассе.
Вы можете использовать отражение в своем коде вместона свой страх и риск, но его не следует использовать , поскольку он может не работать с вашей JVM (изменение модификаторов доступности настоятельно не рекомендуется) или может не работать в следующей версии iText или может не работать по другой причинеЯ не буду добавлять код отражения в свой ответ для дальнейшего предотвращения его использования.
Все, что нам нужно сделать, это переопределить метод drawBorders()
. Вот код, который уже добавляет некоторую случайность в строки.
private static class CustomTableRenderer extends TableRenderer {
public CustomTableRenderer(Table modelElement) {
super(modelElement);
}
@Override
public IRenderer getNextRenderer() {
CustomTableRenderer nextTable = new CustomTableRenderer((Table) modelElement);
nextTable.rows.clear();
nextTable.rowRange = null;
return nextTable;
}
@Override
protected void drawBorders(DrawContext drawContext) {
PdfCanvas canvas = drawContext.getCanvas();
canvas.saveState();
canvas.setStrokeColor(ColorConstants.RED);
Random r = new Random();
// Draw vertical lines
float curX = getOccupiedAreaBBox().getLeft();
for (int i = 0; i <= countedColumnWidth.length; i++) {
canvas.moveTo(curX, getOccupiedAreaBBox().getTop() + 3);
canvas.lineTo(curX + r.nextInt(4), getOccupiedAreaBBox().getBottom() - 3);
if (i < countedColumnWidth.length) {
float curWidth = countedColumnWidth[i];
curX += curWidth;
}
}
// Draw horizontal lines
float curY = getOccupiedAreaBBox().getBottom();
for (int i = 0; i <= heights.size(); i++) {
canvas.moveTo(getOccupiedAreaBBox().getLeft() - 3, curY);
canvas.lineTo(getOccupiedAreaBBox().getRight() + 3, curY + r.nextInt(4));
if (i < heights.size()) {
float curHeight = heights.get(i);
curY += curHeight;
}
}
canvas.stroke();
canvas.restoreState();
}
}
Чтобы активировать пользовательский рендерер, установите его в таблице непосредственно перед добавлением в документ:
PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName));
Document doc = new Document(pdfDoc);
Table table = new Table(UnitValue.createPercentArray(new float[]{30, 30}));
for (int i = 0; i < 40; i++) {
table.addCell(new Cell().add(new Paragraph("Hello")));
table.addCell(new Cell().add(new Paragraph("World")));
table.startNewRow();
}
table.setNextRenderer(new CustomTableRenderer(table));
doc.add(table);
Вот так выглядит результирующая таблица: