如何确定PDF页面中间的正确坐标?
How to decide the right coordinates in the middle of a PDF page?
我是 iText 的新手,我看过它的许多示例。我很难弄清楚的是矩形。在页面上
http://developers.itextpdf.com/examples/form-examples-itext5/multiline-fields
有许多具有 Rectangle 对象硬编码值的示例。例如:
Rectangle rect = new Rectangle(36, 770, 144, 806);
我的问题是我创建了一个段落,我想在它下面添加一个可填写的文本输入框(多行)。我如何知道创建可以很好地放在段落之后的 Rectangle 对象的确切值。段落文本的大小可以改变。所以我不能假设任何硬编码值。
在 iText 5 中,iText 在使用 document.add()
时会跟踪内容的坐标。您可以通过在绝对位置添加内容(例如使用 ColumnText
)来控制自己,但这很难,因为您必须自己跟踪很多事情(例如:您必须在内容到达页面底部)。
如果将坐标的控制权交给 iText,则可以使用页面事件访问这些坐标。
看看下面的示例,我们在 onParagraph()
和 onParagraphEnd()
方法中跟踪 Paragraph
的开始和结束。这段代码示例不容易理解,但它是获取 iText 5 中 Paragraph
坐标的唯一方法,例如,如果我们想在文本块周围绘制一个矩形。正如您在该页面底部看到的那样,iText 7 使满足这一要求变得更加容易。
如果您坚持使用 iText 5,使用通用标签定义位置会容易得多。请参阅 GenericFields example, where we use empty Chunk
s that result in fields. If you want to see a screen shot of the result, see Add PdfPCell to Paragraph
在你的情况下,我会创建一个 Paragraph
,其中包含一个跨越不同行的 Chunk
,并且我会在页面事件的 onGenericTag()
方法中添加该字段.
假设我们有以下文本文件:jekyll_hyde.txt
我们如何将其转换为如下所示的 PDF:
注意添加到标题的蓝色边框,以及每页底部的页码。在 iText 5 中,这些元素是使用页面事件添加的:
class MyPageEvents extends PdfPageEventHelper {
protected float startpos = -1;
protected boolean title = true;
public void setTitle(boolean title) {
this.title = title;
}
@Override
public void onEndPage(PdfWriter writer, Document document) {
Rectangle pagesize = document.getPageSize();
ColumnText.showTextAligned(
writer.getDirectContent(),
Element.ALIGN_CENTER,
new Phrase(String.valueOf(writer.getPageNumber())),
(pagesize.getLeft() + pagesize.getRight()) / 2,
pagesize.getBottom() + 15,
0);
if (startpos != -1)
onParagraphEnd(writer, document,
pagesize.getBottom(document.bottomMargin()));
startpos = pagesize.getTop(document.topMargin());
}
@Override
public void onParagraph(PdfWriter writer, Document document,
float paragraphPosition) {
startpos = paragraphPosition;
}
@Override
public void onParagraphEnd(PdfWriter writer, Document document,
float paragraphPosition) {
if (!title) return;
PdfContentByte canvas = writer.getDirectContentUnder();
Rectangle pagesize = document.getPageSize();
canvas.saveState();
canvas.setColorStroke(BaseColor.BLUE);
canvas.rectangle(
pagesize.getLeft(document.leftMargin()),
paragraphPosition - 3,
pagesize.getWidth() - document.leftMargin() - document.rightMargin(),
startpos - paragraphPosition);
canvas.stroke();
canvas.restoreState();
}
}
我们可以使用下面的代码将一个文本文件转换为PDF,并在PdfWriter
中引入页面事件:
public void createPdf(String dest)
throws DocumentException, IOException {
Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(dest));
MyPageEvents events = new MyPageEvents();
writer.setPageEvent(events);
document.open();
BufferedReader br = new BufferedReader(new FileReader(TEXT));
String line;
Paragraph p;
Font normal = new Font(FontFamily.TIMES_ROMAN, 12);
Font bold = new Font(FontFamily.TIMES_ROMAN, 12, Font.BOLD);
boolean title = true;
while ((line = br.readLine()) != null) {
p = new Paragraph(line, title ? bold : normal);
p.setAlignment(Element.ALIGN_JUSTIFIED);
events.setTitle(title);
document.add(p);
title = line.isEmpty();
}
document.close();
}
我是 iText 的新手,我看过它的许多示例。我很难弄清楚的是矩形。在页面上
http://developers.itextpdf.com/examples/form-examples-itext5/multiline-fields
有许多具有 Rectangle 对象硬编码值的示例。例如:
Rectangle rect = new Rectangle(36, 770, 144, 806);
我的问题是我创建了一个段落,我想在它下面添加一个可填写的文本输入框(多行)。我如何知道创建可以很好地放在段落之后的 Rectangle 对象的确切值。段落文本的大小可以改变。所以我不能假设任何硬编码值。
在 iText 5 中,iText 在使用 document.add()
时会跟踪内容的坐标。您可以通过在绝对位置添加内容(例如使用 ColumnText
)来控制自己,但这很难,因为您必须自己跟踪很多事情(例如:您必须在内容到达页面底部)。
如果将坐标的控制权交给 iText,则可以使用页面事件访问这些坐标。
看看下面的示例,我们在 onParagraph()
和 onParagraphEnd()
方法中跟踪 Paragraph
的开始和结束。这段代码示例不容易理解,但它是获取 iText 5 中 Paragraph
坐标的唯一方法,例如,如果我们想在文本块周围绘制一个矩形。正如您在该页面底部看到的那样,iText 7 使满足这一要求变得更加容易。
如果您坚持使用 iText 5,使用通用标签定义位置会容易得多。请参阅 GenericFields example, where we use empty Chunk
s that result in fields. If you want to see a screen shot of the result, see Add PdfPCell to Paragraph
在你的情况下,我会创建一个 Paragraph
,其中包含一个跨越不同行的 Chunk
,并且我会在页面事件的 onGenericTag()
方法中添加该字段.
假设我们有以下文本文件:jekyll_hyde.txt
我们如何将其转换为如下所示的 PDF:
注意添加到标题的蓝色边框,以及每页底部的页码。在 iText 5 中,这些元素是使用页面事件添加的:
class MyPageEvents extends PdfPageEventHelper {
protected float startpos = -1;
protected boolean title = true;
public void setTitle(boolean title) {
this.title = title;
}
@Override
public void onEndPage(PdfWriter writer, Document document) {
Rectangle pagesize = document.getPageSize();
ColumnText.showTextAligned(
writer.getDirectContent(),
Element.ALIGN_CENTER,
new Phrase(String.valueOf(writer.getPageNumber())),
(pagesize.getLeft() + pagesize.getRight()) / 2,
pagesize.getBottom() + 15,
0);
if (startpos != -1)
onParagraphEnd(writer, document,
pagesize.getBottom(document.bottomMargin()));
startpos = pagesize.getTop(document.topMargin());
}
@Override
public void onParagraph(PdfWriter writer, Document document,
float paragraphPosition) {
startpos = paragraphPosition;
}
@Override
public void onParagraphEnd(PdfWriter writer, Document document,
float paragraphPosition) {
if (!title) return;
PdfContentByte canvas = writer.getDirectContentUnder();
Rectangle pagesize = document.getPageSize();
canvas.saveState();
canvas.setColorStroke(BaseColor.BLUE);
canvas.rectangle(
pagesize.getLeft(document.leftMargin()),
paragraphPosition - 3,
pagesize.getWidth() - document.leftMargin() - document.rightMargin(),
startpos - paragraphPosition);
canvas.stroke();
canvas.restoreState();
}
}
我们可以使用下面的代码将一个文本文件转换为PDF,并在PdfWriter
中引入页面事件:
public void createPdf(String dest)
throws DocumentException, IOException {
Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(dest));
MyPageEvents events = new MyPageEvents();
writer.setPageEvent(events);
document.open();
BufferedReader br = new BufferedReader(new FileReader(TEXT));
String line;
Paragraph p;
Font normal = new Font(FontFamily.TIMES_ROMAN, 12);
Font bold = new Font(FontFamily.TIMES_ROMAN, 12, Font.BOLD);
boolean title = true;
while ((line = br.readLine()) != null) {
p = new Paragraph(line, title ? bold : normal);
p.setAlignment(Element.ALIGN_JUSTIFIED);
events.setTitle(title);
document.add(p);
title = line.isEmpty();
}
document.close();
}