如何使用 iText 将图形绘制为 PDF?

发布于 2024-12-11 02:27:27 字数 665 浏览 0 评论 0原文

我正在尝试完成一个绘制图形并将其写入 PDF 的示例,但我不断收到 PDF 没有页面的错误。如果我在打开后使用 document.add() 添加一些简单的东西,它工作正常,我只是永远看不到图形。这是我的代码:

Document document = new Document();
PdfWriter writer = new PdfWriter();
response.setContentType("application/pdf");
response.setHeader("Content-Disposition",
    " attachment; filename=\"Design.pdf\"");

writer = PdfWriter.getInstance(document, response.getOutputStream());

document.open();    
PdfContentByte cb = writer.getDirectContent();
Graphics2D graphics2D = cb.createGraphics(36, 54);
graphics2D.drawString("Hello World", 36, 54);
graphics2D.dispose();   
document.close();

我是否需要执行其他操作才能将图形添加到文档中,或者我的语法是否不正确?

I am trying to complete an example that draws graphics and writes them to PDF, but I keep getting errors that the PDF has no pages. if I add something simple with document.add() after opening it works fine, I just never see the graphics. Here is my code:

Document document = new Document();
PdfWriter writer = new PdfWriter();
response.setContentType("application/pdf");
response.setHeader("Content-Disposition",
    " attachment; filename=\"Design.pdf\"");

writer = PdfWriter.getInstance(document, response.getOutputStream());

document.open();    
PdfContentByte cb = writer.getDirectContent();
Graphics2D graphics2D = cb.createGraphics(36, 54);
graphics2D.drawString("Hello World", 36, 54);
graphics2D.dispose();   
document.close();

Do I have to do something else to add the graphic to the document or is my syntax incorrect?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

过期情话 2024-12-18 02:27:27

我不是 IText 方面的专家,但上周我尝试用它画一些圆圈。所以这是我在测试过程中注意到的:

如果您绘制图形,则必须(或者可以说我在尝试时必须)将图形命令“包装”在开始的部分中以 saveState() 结尾并以 restoreState() 结尾,并且我需要调用 fillStroke() ——如果我不调用 < code>fillStroke() 那么什么也没有绘制的。

示例

private void circle(float x, float y, PdfWriter writer) {
    PdfContentByte canvas = writer.getDirectContent();

    canvas.saveState();
    canvas.setColorStroke(GrayColor.BLACK);
    canvas.setColorFill(GrayColor.BLACK);
    canvas.circle(x, y, 2);
    canvas.fillStroke();

    canvas.restoreState();
}

@Test
public void testPossition() throws DocumentException, IOException {
    OutputStream outputStream = FileUtil.openOutputStream("testPosition.pdf");
    //this is my personal file util, but it does not anything more
    //then creating a file and opening the file stream.

    Document document = new Document(PageSize.A4, 50, 50, 50, 50);
    PdfWriter writer = PdfWriter.getInstance(document, outputStream);
    document.open();

    markPosition(100, 100, writer);
    document.add(new Paragraph("Total: 595 x 842 -- 72pt (1 inch)"));

    document.close();
    outputStream.flush();
    outputStream.close();
}

private void markPosition(float x, float y, PdfWriter writer)
        throws DocumentException, IOException {
    placeChunck("x: " + x + " y: " + y, x, y, writer);
    circle(x, y, writer);
}

 private void placeChunck(String text, float x, float y, PdfWriter writer)
       throws DocumentException, IOException {
    PdfContentByte canvas = writer.getDirectContent();
    BaseFont font = BaseFont.createFont(BaseFont.HELVETICA,
                  BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
    canvas.saveState();
    canvas.beginText();
    canvas.moveText(x, y);
    canvas.setFontAndSize(font, 9);
    canvas.showText(text);
    canvas.endText();
    canvas.restoreState();
}

但是PdfContentByte(画布)具有更多功能,例如矩形

I am not an expert in IText, but last week I tryed to draw some circles with it. So this is what I have noticed during my tests:

If you draw graphics, you must (or lets say I must when I tryed it) "wrap" the graphics commands in a section starting with saveState() and ending with restoreState(), es well as I needed to invoke fillStroke() -- if I do not invoke fillStroke() then nothing was drawn.

Example

private void circle(float x, float y, PdfWriter writer) {
    PdfContentByte canvas = writer.getDirectContent();

    canvas.saveState();
    canvas.setColorStroke(GrayColor.BLACK);
    canvas.setColorFill(GrayColor.BLACK);
    canvas.circle(x, y, 2);
    canvas.fillStroke();

    canvas.restoreState();
}

@Test
public void testPossition() throws DocumentException, IOException {
    OutputStream outputStream = FileUtil.openOutputStream("testPosition.pdf");
    //this is my personal file util, but it does not anything more
    //then creating a file and opening the file stream.

    Document document = new Document(PageSize.A4, 50, 50, 50, 50);
    PdfWriter writer = PdfWriter.getInstance(document, outputStream);
    document.open();

    markPosition(100, 100, writer);
    document.add(new Paragraph("Total: 595 x 842 -- 72pt (1 inch)"));

    document.close();
    outputStream.flush();
    outputStream.close();
}

private void markPosition(float x, float y, PdfWriter writer)
        throws DocumentException, IOException {
    placeChunck("x: " + x + " y: " + y, x, y, writer);
    circle(x, y, writer);
}

 private void placeChunck(String text, float x, float y, PdfWriter writer)
       throws DocumentException, IOException {
    PdfContentByte canvas = writer.getDirectContent();
    BaseFont font = BaseFont.createFont(BaseFont.HELVETICA,
                  BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
    canvas.saveState();
    canvas.beginText();
    canvas.moveText(x, y);
    canvas.setFontAndSize(font, 9);
    canvas.showText(text);
    canvas.endText();
    canvas.restoreState();
}

But PdfContentByte (canvas) has much more functions, for example rectangle.

瀟灑尐姊 2024-12-18 02:27:27

是否 Document doc = new Document(PageSize.A4);
有什么区别吗?

我不知道您是否需要添加这样的 Paragraph

doc.add(new Paragraph(...));

我们还使用 doc.add(ImgRaw); 来添加图像。

Does Document doc = new Document(PageSize.A4);
make any difference?

I don't know if you need to add a Paragraph like this:

doc.add(new Paragraph(...));

Also we use doc.add(ImgRaw); to add images.

烧了回忆取暖 2024-12-18 02:27:27

无需深入探讨,我认为您的总体方法很好。我认为这里可能发生的情况是 Graphics2D 原点与 PDF 原点不同,所以也许您需要更改对 drawString() 的调用,以便它使用 0,0 作为位置?

Without going too far into it, I think your general approach is fine. I think what might be happening here is that the Graphics2D origin is different from the PDF origin, so maybe you need to change the call to drawString() so it uses 0,0 as the location??

叹梦 2024-12-18 02:27:27

我认为问题在于 directcontent 直接写入页面对象。这样您就可以添加背景或背景图像。在写入 directcontent 之前尝试添加一个新页面 (doc.newPage())。

I think the problem is that directcontent writes directly to the page object. This way you can add backgrounds or backdrop images. Try adding a new page (doc.newPage()) before writing to the directcontent.

白云悠悠 2024-12-18 02:27:27

您是否尝试过在 g2d 对象上仅使用形状而不是文本进行绘图操作?这将消除字体选择或类似问题发生奇怪情况的可能性。

iText In Action 第 12 章正是您所寻找的内容 - 确实值得学习。 第12章预览

Have you tried drawing operations on the g2d object that just use shapes instead of text? That would eliminate the possibility of something odd going on with font selection or something like that.

iText In Action Chapter 12 has exactly what you are looking for - it really is worth picking up. Preview of Chapter 12

草莓味的萝莉 2024-12-18 02:27:27

我刚刚针对 iText 的最新 HEAD 进行了以下单元测试:

    Document document = new Document();
    PdfWriter writer = new PdfWriter();
    ByteArrayOutputStream baos = new ByteArrayOutputStream();

    writer = PdfWriter.getInstance(document, baos);

    document.open();    
    PdfContentByte cb = writer.getDirectContent();
    Graphics2D graphics2D = cb.createGraphics(36, 54);
    graphics2D.setColor(Color.black);
    graphics2D.drawRect(0, 0, 18, 27);

    Font font = new Font("Serif", Font.PLAIN, 10);
    graphics2D.setFont(font);

    graphics2D.drawString("Yo Adrienne", 0, 54); 


    graphics2D.dispose();   
    document.close();

    TestResourceUtils.openBytesAsPdf(baos.toByteArray());

它工作正常 - 我在页面的左下角看到一个黑色的小矩形,加上文本。请注意,我为我的drawString 方法指定了X=0(您指定了36,这会导致文本呈现在图像边界之外)。另请注意,我明确指定了一种字体 - 如果我忽略它,它仍然会呈现,但不信任此类事情的默认值通常是一个好主意。最后,我明确设置了前景色——同样,这并不是真正必要的,但信任默认值可能会很可怕。

所以我不得不说这里的核心问题是文本在 x=36 处的位置。

在我的所有测试中,我都无法创建一个错误,指出 PDF 没有页面 - 您可以发布您收到的异常的堆栈跟踪吗?

我无法想象在文档中添加一个段落对此有任何影响(这是很久很久以前就已经得到解决的那种错误)

I just put together the following unit test against the latest HEAD of iText:

    Document document = new Document();
    PdfWriter writer = new PdfWriter();
    ByteArrayOutputStream baos = new ByteArrayOutputStream();

    writer = PdfWriter.getInstance(document, baos);

    document.open();    
    PdfContentByte cb = writer.getDirectContent();
    Graphics2D graphics2D = cb.createGraphics(36, 54);
    graphics2D.setColor(Color.black);
    graphics2D.drawRect(0, 0, 18, 27);

    Font font = new Font("Serif", Font.PLAIN, 10);
    graphics2D.setFont(font);

    graphics2D.drawString("Yo Adrienne", 0, 54); 


    graphics2D.dispose();   
    document.close();

    TestResourceUtils.openBytesAsPdf(baos.toByteArray());

And it works fine - I get a small black rectangle in the lower left hand corner of the page, plus text. Note that I am specifying X=0 for my drawString method (you were specifying 36 which causes the text to render outside of the image bounds). Note also that I explicitly specified a font - if I leave that out, it still renders, but it's usually a great idea to not trust the defaults for that sort of thing. Finally, I explicitly set the foreground color - again, not truly necessary, but trusting defaults can be scary.

So I'd have to say that the core issue here was the placement of the text at x=36.

In none of my tests was I able to create an error saying that the PDF has no pages - can you post the stack trace of the exception you are getting?

I can't imagine that adding a paragraph to the document makes any difference to this (that's the sort of bug that would have gotten taken care of long, long ago)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文