【问题标题】:pdfBox add different lines to pdfpdfBox 向 pdf 添加不同的行
【发布时间】:2016-04-19 08:23:15
【问题描述】:

我正在研究生成一个 pdf 文档。目前我正在尝试不同的方法。我想在 pdf 文档中获得不止一行。使用我想出的HelloWorld 代码示例...

package org.apache.pdfbox.examples.pdmodel;

import java.io.IOException;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;

import org.apache.pdfbox.pdmodel.PDPageContentStream;

import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.font.PDType1Font;

/**
 * Creates a "Hello World" PDF using the built-in Helvetica font.
 *
 * The example is taken from the PDF file format specification.
 */
public final class HelloWorld
{
    private HelloWorld()
    {
    }

    public static void main(String[] args) throws IOException
    {

        String filename = "line.pdf";
        String message = "line";

        PDDocument doc = new PDDocument();
        try
        {
            PDPage page = new PDPage();
            doc.addPage(page);

            PDFont font = PDType1Font.HELVETICA_BOLD;

            PDPageContentStream contents = new PDPageContentStream(doc, page);
            contents.beginText();
            contents.setFont(font, 12);
            // Loop to create 25 lines of text
            for (int y = 0; y< 25; y++) {
                int ty = 700 + y * 15;
                contents.newLineAtOffset(100, ty);
                //contents.newLineAtOffset(125, ty);
                //contents.showText(Integer.toString(i));
                contents.showText(message + " " + Integer.toString(i));
                System.out.println(message + " " + Integer.toString(i));
            }
            contents.endText();
            contents.close();

            doc.save(filename);
        }
        finally
        {
            doc.close();
            System.out.println("HelloWorld finished after 'doc.close()'.");
        }
    }
}

但查看我生成的文档,我只看到“第 0 行”一次,没有其他行。我做错了什么?

【问题讨论】:

    标签: java pdf pdfbox


    【解决方案1】:

    您的问题是您认为PDPageContentStream.newLineAtOffset 使用绝对坐标。情况并非如此,它使用相对坐标,参见。 JavaDocs:

    /**
     * The Td operator.
     * Move to the start of the next line, offset from the start of the current line by (tx, ty).
     *
     * @param tx The x translation.
     * @param ty The y translation.
     * @throws IOException If there is an error writing to the stream.
     * @throws IllegalStateException If the method was not allowed to be called at this time.
     */
    public void newLineAtOffset(float tx, float ty) throws IOException
    

    所以您的附加行远离可见页面区域。

    因此,您可能想要这样的东西:

    ...
    contents.beginText();
    contents.setFont(font, 12);
    contents.newLineAtOffset(100, 700);
    // Loop to create 25 lines of text
    for (int i = 0; i < 25; i++) {
        contents.showText(message + " " + Integer.toString(i));
        System.out.println(message + " " + Integer.toString(i));
        contents.newLineAtOffset(0, -15);
    }
    contents.endText();
    ...
    

    在这里,您从 100、700 开始,每行向下移动 15。

    【讨论】:

    • 我是否正确假设文档的 (0,0) 坐标位于左下角?所以你的contents.newLineAtOffset(0, -15); 向上移动了?
    • 0,0 是左下角,是的,但随后contents.newLineAtOffset(100, 700) 向上移动一点,然后每个contents.newLineAtOffset(0, -15) 再次向下移动一行。
    • 感谢反馈
    • 但是 x 和 y 平移的单位是什么?毫米?英寸?像素?
    • 它们是当前用户空间单元。如果您没有更改用户空间坐标系,则它们默认为 1/72 英寸的点。
    【解决方案2】:

    除了 mkl 的回答之外,您还可以为每一行创建一个新的文本操作。这样做将使您能够使用绝对坐标。

    ...
    contents.setFont(font, 12);
    // Loop to create 25 lines of text
    for (int i = 0; i < 25; i++) {
        int ty = 700 + y * 15;
        contents.beginText();
        contents.newLineAtOffset(100, ty);
        contents.showText(message + " " + Integer.toString(i));
        System.out.println(message + " " + Integer.toString(i))
        contents.endText();
    }
    ...
    

    您是否需要这个取决于您的用例。
    例如,我想写一些右对齐的文本。在这种情况下,使用绝对位置更容易,所以我创建了一个这样的辅助方法:

    public static void showTextRightAligned(PDPageContentStream contentStream, PDType1Font font, int fontsize, float rightX, float topY, String text) throws IOException
    {
        float textWidth = fontsize * font.getStringWidth(text) / 1000;
        float leftX = rightX - textWidth;
        contentStream.beginText();
        contentStream.newLineAtOffset(leftX, topY);
        contentStream.showText(text);
        contentStream.endText();
    }
    

    【讨论】:

    • int ty = 700 + y * 15; --- 我猜你的意思是int ty = 700 - y * 15;。除此之外,您是对的,结果基本相同。流可能有点大,但实际上只有一点。
    猜你喜欢
    • 2019-01-17
    • 2014-05-31
    • 2018-02-07
    • 1970-01-01
    • 1970-01-01
    • 2017-01-29
    • 1970-01-01
    • 1970-01-01
    • 2016-09-29
    相关资源
    最近更新 更多