gpt4 book ai didi

java - 在 itext7 中更灵活地绘制自定义表格边框

转载 作者:行者123 更新时间:2023-12-02 01:30:45 33 4
gpt4 key购买 nike

之前我问过一个关于绘制自定义表格边框的问题:Draw custom borders for table spanning across more than one page in itext7

并且提供了一种绘制自定义边框的方法,但它不允许影响完整的行或列线(例如稍微倾斜),因为单元格边框是为每个单元格单独绘制的。

我想为表格边框添加一些随机性,如下面的屏幕截图所示:

table borders

这是我的代码,适用于适合单个页面的表格,但如果表格跨越多个页面,则代码不再起作用:

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 的私有(private)实现细节,因此将来可能无法工作。它适用于 7.1.6,这是撰写本文时最新发布的版本。您应该为此目的创建一个自定义代码分支。 Pull requests也欢迎。

如果我们查看 TableRenderer 的实现,我们会发现该类包含 heights ( line in code ) 和 countedColumnWidth ( line in code ) )听起来很有趣的字段,但它们是私有(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);

结果表如下所示:

result

关于java - 在 itext7 中更灵活地绘制自定义表格边框,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56101827/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com