![](/img/trans.png)
[英]Draw custom borders for table spanning across more than one page in itext7
[英]Draw custom borders for table with more flexibility in itext7
以前我問過一個有關繪制自定義表格邊框的問題: 在itext7中為跨表格的表格繪制自定義邊框
答案提供了一種繪制自定義邊框的方法,但是它不允許影響完整的行或列線(例如,將其稍微傾斜),因為為每個單元格分別繪制了單元格邊框。
我想在表格邊框中添加一些隨機性,如以下屏幕截圖所示:
這是我適用於適合單個頁面的表的代碼,但是如果表跨多個頁面,則該代碼將不再起作用:
PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
Document doc = new Document(pdfDoc);
doc.add(new Paragraph("Table event"));
Table table = new Table(UnitValue.createPercentArray(3)).useAllAvailableWidth();
table.setNextRenderer(new DottedLineTableRenderer(table, new Table.RowRange(0, 0)));
String s ="";
for(int i=0;i<35;i++){
s+="\nTest";
}
table.addCell(new Cell().add(new Paragraph(s)).setBorder(Border.NO_BORDER));
table.addCell(new Cell().add(new Paragraph("A2")).setBorder(Border.NO_BORDER));
table.addCell(new Cell().add(new Paragraph("A3")).setBorder(Border.NO_BORDER));
doc.add(table);
doc.close();
private class DottedLineTableRenderer extends TableRenderer {
public DottedLineTableRenderer(Table modelElement, Table.RowRange rowRange) {
super(modelElement, rowRange);
}
@Override
public void drawChildren(DrawContext drawContext) {
super.drawChildren(drawContext);
PdfCanvas canvas = drawContext.getCanvas();
int maxLineTo = 5;
int minLineTo = 2;
int lineToHorizontalLine = (int)(Math.random() * maxLineTo) + minLineTo;
int maxSkewHor = 5;
int minSkewHor = 2;
int skewHorizontalLine = (int)(Math.random() * maxSkewHor) + minSkewHor;
int maxVerticalLine = 5;
int minVerticalLine = 2;
int lineToVerticalLine = (int)(Math.random() * maxVerticalLine) + minVerticalLine;
canvas.setLineWidth(2).setStrokeColor(new DeviceRgb(222, 27, 27));
// first horizontal line
CellRenderer[] cellRenderers = rows.get(0);
canvas.moveTo(cellRenderers[0].getOccupiedArea().getBBox().getLeft()-lineToHorizontalLine,
cellRenderers[0].getOccupiedArea().getBBox().getTop());
canvas.lineTo(cellRenderers[cellRenderers.length - 1].getOccupiedArea().getBBox().getRight()+lineToHorizontalLine,
cellRenderers[cellRenderers.length - 1].getOccupiedArea().getBBox().getTop());
for (int i = 0; i < rows.size(); i++) {
skewHorizontalLine = (int)(Math.random() * maxSkewHor) + minSkewHor;
lineToHorizontalLine = (int)(Math.random() * maxLineTo) + minLineTo;
cellRenderers = rows.get(i);
// horizontal lines
canvas.moveTo(cellRenderers[0].getOccupiedArea().getBBox().getX()-lineToHorizontalLine,
cellRenderers[0].getOccupiedArea().getBBox().getY()+skewHorizontalLine);
canvas.lineTo(cellRenderers[cellRenderers.length - 1].getOccupiedArea().getBBox().getRight()+lineToHorizontalLine,
cellRenderers[cellRenderers.length - 1].getOccupiedArea().getBBox().getBottom());
// first vertical line
Rectangle cellRect = cellRenderers[0].getOccupiedArea().getBBox();
canvas.moveTo(cellRect.getLeft(), cellRect.getBottom());
canvas.lineTo(cellRect.getLeft(), cellRect.getTop()+lineToVerticalLine );
// vertical lines
for (int j = 0; j < cellRenderers.length; j++) {
lineToVerticalLine = (int)(Math.random() * maxVerticalLine) + minVerticalLine;
cellRect = cellRenderers[j].getOccupiedArea().getBBox();
canvas.moveTo(cellRect.getRight(), cellRect.getBottom()-lineToVerticalLine);
canvas.lineTo(cellRect.getRight(), cellRect.getTop()+lineToVerticalLine); //ячейки
}
}
canvas.stroke();
}
}
我想自己繪制自定義邊框:)
首先,我們需要正確地覆蓋渲染器,即,覆蓋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);
結果表如下所示:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.