之前,我问过一个有关绘制自定义表格边框的问题:Draw custom borders for table spanning across more than one page in 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();
}
}
我想自己绘制自定义边框:)
答案 0 :(得分:2)
首先,我们需要正确覆盖渲染器,即覆盖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
是撰写本文时的最新发布版本。为此,您应该创建代码的自定义派生。也欢迎Pull requests。
如果我们看一下heights
的实现,就会发现该类包含countedColumnWidth
(line in code)和private
(line in code)字段,听起来很有趣,但它们是protected
。这意味着我们应该创建iText的自定义分支(源代码可在https://github.com/itext/itext7中使用),将这些字段设置为drawBorders()
,并在子类中使用它们。
您可以在代码中使用反射代替,但后果自负,但不应,因为它可能不适用于您的JVM(强烈建议不要更改可访问性修饰符)或可能无法在其中使用,下一版本的iText,或者由于其他原因可能无法正常工作。我不会在答案中添加反射代码,以进一步阻止其使用。
我们需要做的就是覆盖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);
要激活自定义渲染器,请在添加到文档之前将其设置为表格:
import time
seconds = time.time();
result = time.ctime(seconds);
if(result.tm_year==y &&result.tm_mday==d &&result.tm_hour==h)
{
}
这是结果表的样子: