如何确定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 Chunks 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();
}

来源:developers.itextpdf.com