【问题标题】:How to decide the right coordinates in the middle of a PDF page?如何确定 PDF 页面中间的正确坐标?
【发布时间】:2020-07-04 19:20:41
【问题描述】:

我是 iText 的新手,我查看了它的许多示例。我很难弄清楚的是矩形。在页面上

http://developers.itextpdf.com/examples/form-examples-itext5/multiline-fields

有许多硬编码 Rectangle 对象值的示例。例如:

Rectangle rect = new Rectangle(36, 770, 144, 806);

我的问题是我创建了一个段落,我想在它下面添加一个可填充的文本输入框(多行)。我如何知道创建可以很好地放在段落之后的 Rectangle 对象的确切值。段落文本的大小可以更改。所以我不能假设任何硬编码的值。

【问题讨论】:

    标签: itext


    【解决方案1】:

    在 iText 5 中,iText 在使用document.add() 时会跟踪内容的坐标。您可以通过在绝对位置添加内容来控制自己(例如通过使用ColumnText),但这很难,因为您必须自己跟踪很多事情(例如:当内容到达时您必须自己引入分页符页面底部)。

    如果您将坐标的控制权留给 iText,则可以通过使用页面事件来访问这些坐标。

    看看下面的例子,我们在onParagraph()onParagraphEnd() 方法中跟踪Paragraph 的开始和结束。此代码示例不容易理解,但它是在 iText 5 中获取 Paragraph 坐标的唯一方法,例如,如果我们想在文本块周围绘制一个矩形。正如您在该页面底部看到的那样,iText 7 使满足这一要求变得更加容易。

    如果您坚持使用 iText 5,则使用通用标签来定义位置会容易得多。请参阅GenericFields 示例,我们使用空的Chunks 生成字段。如果您想查看结果的屏幕截图,请参阅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

    【讨论】:

    • 我会看看你推荐的!
    • 布鲁诺,谢谢。我浏览了您的链接,很难产生您所说的“在您的情况下,我将创建一个包含跨越不同行的块的段落,并且我将在页面事件的 onGenericTag() 方法中添加该字段。”是的,我想在段落之后有多行输入框。网上有这样的例子吗?最好的。
    • GenericFields 示例显示了当您想在Paragraph 中添加字段inside 时如何完成。只需修改该示例,使Chunk 跨越完整的Paragraph。这应该不难。
    • 我看到您也在尝试使用表格。使用PdfPCell 事件在表中添加多行字段。官方网站上有不同的示例。
    猜你喜欢
    • 2019-01-22
    • 2013-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-07
    • 1970-01-01
    • 1970-01-01
    • 2020-09-11
    相关资源
    最近更新 更多