java - 在工作中itext如何找出坐标文本?
问题描述
我想知道添加到页面的文本的坐标。并将一些画布应用于此文本。(例如自定义下划线或删除线或三角形内的文本)
我只需要某些词
List<String> listString = new ArraList();
PdfDocument pdfDoc = new PdfDocument(new PdfWriter(DEST));
Document doc = new Document(pdfDoc, PageSize.A4);
for(String s:listString)
//**underlineWord** hidden it will be removed
if( s.contains("**underlineWord**")){
s.replace("**underlineWord**","");
Text text = new Text(s)
Float[] coords = getCoords(text)
Canvas canvas = new Canvas(...);
setCustomUderline(coords)
}
doc.add(new Paragraph(text) );
我知道 PdfCanvasProcessor,但我不使用它,因为我不知道某些单词,(其中包含**underlineWord**
)
解决方案
在 iText7 中,您使用自定义的Renderer
. 该技术在DashedUnderline
示例中显示:
PdfDocument pdfDoc = new PdfDocument(new PdfWriter(DEST));
Document doc = new Document(pdfDoc);
doc.add(new Paragraph("This text is not underlined"));
Text text1 = new Text("This text is underlined with a solid line");
text1.setUnderline(1, -3);
doc.add(new Paragraph(text1));
Text text2 = new Text("This text is underlined with a dashed line");
text2.setNextRenderer(new DashedLineTextRenderer(text2));
doc.add(new Paragraph(text2));
doc.close();
即,您只需为有问题Renderer
的Text
位设置一个自定义。在手头的示例中,自定义Renderer
类是
protected class DashedLineTextRenderer extends TextRenderer {
public DashedLineTextRenderer(Text textElement) {
super(textElement);
}
@Override
public void draw(DrawContext drawContext) {
super.draw(drawContext);
Rectangle rect = this.getOccupiedAreaBBox();
PdfCanvas canvas = drawContext.getCanvas();
canvas
.saveState()
.setLineDash(3, 3)
.moveTo(rect.getLeft(), rect.getBottom() - 3)
.lineTo(rect.getRight(), rect.getBottom() - 3)
.stroke()
.restoreState();
}
}
如您所见,您可以覆盖draw
以首先调用super
实现以正常绘制文本。之后,您可以通过调用检索用于绘制文本的区域getOccupiedAreaBBox
并将其用于您的任务,无论是用于装饰文本还是仅将位置存储在某处。
如果您想知道为什么此示例位于events
子包中...该示例对应于 iText5 示例,并且在 iText5 中,您通过将通用标签设置为有Chunk
问题并在onGenericTag
页面事件侦听器的方法,请参阅此答案以获取示例。
在你问的评论中
我可以用桌子做吗?(使用帮助画布绘制边框)
是的,您再次为此使用相关的渲染器,例如参见DottedLineCell
示例:
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, 2)));
table.addCell(new Cell().add(new Paragraph("A1")).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));
table.addCell(new Cell().add(new Paragraph("B1")).setBorder(Border.NO_BORDER));
table.addCell(new Cell().add(new Paragraph("B2")).setBorder(Border.NO_BORDER));
table.addCell(new Cell().add(new Paragraph("B3")).setBorder(Border.NO_BORDER));
table.addCell(new Cell().add(new Paragraph("C1")).setBorder(Border.NO_BORDER));
table.addCell(new Cell().add(new Paragraph("C2")).setBorder(Border.NO_BORDER));
table.addCell(new Cell().add(new Paragraph("C3")).setBorder(Border.NO_BORDER));
doc.add(table);
doc.add(new Paragraph("Cell event"));
table = new Table(UnitValue.createPercentArray(1)).useAllAvailableWidth();
Cell cell = new Cell().add(new Paragraph("Test"));
cell.setNextRenderer(new DottedLineCellRenderer(cell));
cell.setBorder(Border.NO_BORDER);
table.addCell(cell.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();
canvas.setLineDash(3f, 3f);
// first horizontal line
CellRenderer[] cellRenderers = rows.get(0);
canvas.moveTo(cellRenderers[0].getOccupiedArea().getBBox().getLeft(),
cellRenderers[0].getOccupiedArea().getBBox().getTop());
canvas.lineTo(cellRenderers[cellRenderers.length - 1].getOccupiedArea().getBBox().getRight(),
cellRenderers[cellRenderers.length - 1].getOccupiedArea().getBBox().getTop());
for (int i = 0; i < rows.size(); i++) {
cellRenderers = rows.get(i);
// horizontal lines
canvas.moveTo(cellRenderers[0].getOccupiedArea().getBBox().getX(),
cellRenderers[0].getOccupiedArea().getBBox().getY());
canvas.lineTo(cellRenderers[cellRenderers.length - 1].getOccupiedArea().getBBox().getRight(),
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());
// vertical lines
for (int j = 0; j < cellRenderers.length; j++) {
cellRect = cellRenderers[j].getOccupiedArea().getBBox();
canvas.moveTo(cellRect.getRight(), cellRect.getBottom());
canvas.lineTo(cellRect.getRight(), cellRect.getTop());
}
}
canvas.stroke();
}
}
和
private class DottedLineCellRenderer extends CellRenderer {
public DottedLineCellRenderer(Cell modelElement) {
super(modelElement);
}
@Override
public void draw(DrawContext drawContext) {
super.draw(drawContext);
drawContext.getCanvas().setLineDash(3f, 3f);
drawContext.getCanvas().rectangle(this.getOccupiedArea().getBBox());
drawContext.getCanvas().stroke();
}
}
分别。
正如Alexey Subach在此答案中所解释的那样,完全自定义 aRenderer
也应该覆盖该getNextRenderer()
方法。特别是如果相关对象中可能发生区域中断,这是必要的,否则自定义仅适用于 OP 观察到的第一个区域。
推荐阅读
- react-native - 如何在本机反应中获取文件夹大小和长度
- google-apps-script - 带有空白行的自动填充数据 - Google 表格/Google Apps 脚本
- microsoft-teams - MS TEAMS - 向所有团队成员发送特定频道帖子的邮件通知
- wordpress - 迁移后 WordPress 图像未加载
- html - 为什么模态显示而不调用它?
- sympy - 点到线的距离:输出nan?
- vb.net - 从 DBF 到带有编码的 Visual Studio 的字符串
- c++ - 在反转字符串“my.name.is”时,我得到的输出为“is@.name.my”。我不明白“@”是从哪里来的
- asp.net - 为什么我的 webapp 在以 iis express 运行时只提供 css 文件?
- java - Sonarqube - 渔获量应该结合起来