iText 7: Установите изображение для кнопки, которая появляется несколько раз - PullRequest
0 голосов
/ 09 января 2019

У меня есть простой PDF-файл с полем кнопки, которое я хотел бы заполнить изображением.

Поле кнопки появляется в документе несколько раз. Я хотел бы установить изображение один раз на уровне поля, чтобы оно появлялось при каждом появлении поля.

PDF , который я использую для тестирования.

Код, который не работает:

ByteArrayOutputStream outStr = new ByteArrayOutputStream();

PdfDocument pdfDocument = new PdfDocument(new PdfReader(pdfStr), new PdfWriter(outStr));
PdfAcroForm acroForm = PdfAcroForm.getAcroForm(pdfDocument, false);

PdfButtonFormField button = (PdfButtonFormField) acroForm.getField("image");
button.setImage("src/test/resources/my_image.png");

acroForm.flattenFields();

pdfDocument.close();

Исключение, которое выдается:

com.example.documents.DocumentServiceException: Fail to render form
    at com.example.ITEXTTests.test(ITEXTTests.java:100)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: java.lang.IllegalArgumentException
    at com.itextpdf.layout.element.Text.<init>(Text.java:69)
    at com.itextpdf.layout.element.Paragraph.<init>(Paragraph.java:80)
    at com.itextpdf.forms.fields.PdfFormField.drawButton(PdfFormField.java:3226)
    at com.itextpdf.forms.fields.PdfFormField.drawPushButtonAppearance(PdfFormField.java:3199)
    at com.itextpdf.forms.fields.PdfFormField.regenerateField(PdfFormField.java:2106)
    at com.itextpdf.forms.PdfAcroForm.flattenFields(PdfAcroForm.java:661)
    at com.example.ITEXTTests.test(ITEXTTests.java:98)
    ... 23 more

Я использую iText 7.1.4 (последний выпуск 7.x).

1 Ответ

0 голосов
/ 09 января 2019

Фактическая проблема не в выравнивании (во время которого возникает исключение в 7.1.4; это исключение больше не возникает в текущем 7.1.5-SNAPSHOT), уже установка значения не выполняется (как в 7.1.4, так и в 7.1 .5-SNAPSHOT на данный момент); Вы можете проверить это, выполнив код без строки acroForm.flattenFields() и проверив вывод.

На самом деле текущая реализация PdfFormField.regenerateField() (которая вызывается при установке значения поля), по-видимому, не поддерживает поля с несколькими виджетами, в частности в контексте полей с кнопками (но также и для других типов полей) он предполагает объединение абстрактного объекта поля формы и его виджета (что возможно только для полей с одним виджетом) как при извлечении из него информации, так и при добавлении к ней сгенерированного внешнего вида.

Таким образом, ваш вариант использования

Поле кнопки появляется в документе несколько раз. Я хотел бы установить изображение один раз на уровне поля, чтобы оно появлялось при каждом появлении поля.

еще не поддерживается iText 7, по крайней мере, не в текущей версии 7.1.5-SNAPSHOT.


Обходной путь должен был бы заменить

button.setImage("src/test/resources/my_image.png");

от

ImageData img = ImageDataFactory.create("src/test/resources/my_image.png");
PdfImageXObject imgXObj = new PdfImageXObject(img);
List<PdfWidgetAnnotation> widgets = button.getWidgets();
for (PdfWidgetAnnotation widget : widgets) {
    Rectangle rectangle = widget.getRectangle().toRectangle();
    PdfFormXObject xObject = new PdfFormXObject(rectangle);
    PdfCanvas canvas = new PdfCanvas(xObject, pdfDocument);
    canvas.addXObject(imgXObj, rectangle.getWidth(), 0, 0, rectangle.getHeight(), rectangle.getLeft(), rectangle.getBottom());
    widget.setNormalAppearance(xObject.getPdfObject());
}

( SetButtonImage test testSetImageToButtonWithManyVisualizationsWorkAround)

Используя текущий 7.1.5-SNAPSHOT, это работает, включая выравнивание.

Осторожно, это не идеальное исправление отсутствующей поддержки кнопок для нескольких виджетов, код игнорирует некоторые настройки (например, границы кнопки и ширину полосы вокруг изображения) и, возможно, растягивает изображение неожиданно путь. Кроме того, он проверен только на вашем примере PDF. Таким образом, он действительно может служить временным решением проблемы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...