Как мне рисовать графику в PDF с помощью iText?

#java #spring-mvc #pdf-generation #itext #graphics2d

#java #spring-mvc #генерация PDF #itext #graphics2d

Вопрос:

Я пытаюсь завершить пример, который рисует графику и записывает их в 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();
  

Должен ли я сделать что-то еще, чтобы добавить графику в документ, или мой синтаксис неверен?

Комментарии:

1. Поэтому добавление пустого места или чего-либо еще в документ сначала перед добавлением графики исправило это для меня. Собираюсь отметить правильность Стикена, поскольку это может быть то, что он пытался мне сказать. Если кто-нибудь захочет объяснить это, я назначу награду.

Ответ №1:

Я не эксперт в iText, но на прошлой неделе я попытался нарисовать с его помощью несколько кругов. Итак, это то, что я заметил во время своих тестов:

Если вы рисуете графику, вы должны (или, скажем, я должен, когда я попробовал это) «обернуть» графические команды в раздел, начинающийся с saveState() и заканчивающийся restoreState() , а также мне нужно было вызвать fillStroke() — если я не вызываю 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 Например, But (canvas) имеет гораздо больше функций rectangle .

Ответ №2:

Имеет ли Document doc = new Document(PageSize.A4); какое-либо значение?

Я не знаю, нужно ли вам добавлять Paragraph подобное:

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

Также мы используем doc.add(ImgRaw); для добавления изображений.

Комментарии:

1. Объекты Graphics2D не принимаются в doc.add() как строки или изображения. Попробовал формат страницы A4, но безуспешно.

2. Также попытался добавить объект Graphics2D в абзац, поскольку он принимает объекты, а затем добавить абзац в документ, но получил «Вставка недопустимого элемента: PdfGraphics2D не может быть приведен к элементу»

Ответ №3:

Не вдаваясь в подробности, я думаю, что ваш общий подход хорош. Я думаю, что здесь может произойти то, что источник Graphics2D отличается от источника PDF, поэтому, возможно, вам нужно изменить вызов на drawString(), чтобы он использовал 0,0 в качестве местоположения??

Комментарии:

1. Я пробовал это, но все та же ошибка (исключение java.io.IOException: в документе нет страниц). Как будто он ничего не пытается написать.

2. Также пробовал (0,54), поскольку я полагаю, что система координат PDF по оси y увеличивается, а graphics2d снижается, но результат тот же.

3. О — я недостаточно внимательно читал — Проблема с документом не связана с проблемой системы координат — извините за отвлечение.

4. iText корректирует систему координат для вас. Никаких проблем нет.

Ответ №4:

Я думаю, проблема в том, что directcontent записывает непосредственно в объект страницы. Таким образом, вы можете добавлять фоны или фоновые изображения. Попробуйте добавить новую страницу ( doc.newPage() ) перед записью в directcontent.

Комментарии:

1. Тот же результат; Я был уверен, что это, по крайней мере, откроет PDF с пустой страницей, но с той же ошибкой.

2. Вы пробовали смотреть на примеры в itextpdf.com/themes/keyword.php?id=56 ? Может быть, они могут вам помочь…

Ответ №5:

Вы пробовали операции рисования на объекте g2d, которые просто используют фигуры вместо текста? Это исключило бы возможность чего-то странного с выбором шрифта или что-то в этом роде.

В главе 12 iText в действии есть именно то, что вы ищете — это действительно стоит взять. Предварительный просмотр главы 12

Комментарии:

1. Я попробовал несколько простых прямоугольников и даже линий.

Ответ №6:

Я только что собрал следующий модульный тест для последней главы 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());
  

И это работает нормально — я получаю маленький черный прямоугольник в нижнем левом углу страницы плюс текст. Обратите внимание, что я указываю X = 0 для моего метода drawString (вы указывали 36, что приводит к отображению текста за пределами границ изображения). Обратите внимание также, что я явно указал шрифт — если я оставлю это, он все равно будет отображаться, но обычно отличная идея не доверять значениям по умолчанию для такого рода вещей. Наконец, я явно задаю цвет переднего плана — опять же, это не обязательно, но доверять значениям по умолчанию может быть страшно.

Итак, я должен сказать, что основной проблемой здесь было размещение текста при x = 36.

Ни в одном из моих тестов я не смог создать ошибку, в которой говорилось, что в PDF-файле нет страниц — можете ли вы опубликовать трассировку стека исключения, которое вы получаете?

Я не могу себе представить, что добавление абзаца в документ имеет какое-либо значение для этого (это ошибка, о которой давно бы позаботились)