我一直在关注“第 8 章:填写交互式表单”iText 示例(代码和 pdf 位于 http://itextpdf.com/examples/iia.php?id=154 ),并注意到一些与外观相关的问题,这些问题也体现在示例 pdf 中。
该示例具有单选按钮列表(圆圈内的经典点)和复选框列表(带有红色背景的交叉框)。到目前为止,一切都很好。然而,以编程方式填写这些字段后生成的 pdf 在视觉上不一致。单选按钮已全部恢复为正方形,并且选定的(“西类牙语”)内部有一个十字形(?)十字而不是点。这些字段仍然可以编辑。当我选择不同的单选按钮时,之前选择的单选按钮将恢复为空圆圈。新选择的字段已从空方 block 变为虚线圆圈。这也可以通过复选框观察到。
有什么办法可以在填充字段的同时保留其原始外观吗?
谢谢!
编辑 - 这是我使用的代码的简化:
public void buildPdf() throws Exception {
Document document = new Document(PageSize.A4);
File file = new File("/test.pdf");
final PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(file));
document.open();
PdfPCell cell = new PdfPCell();
PdfRadioGroupTable group = new PdfRadioGroupTable("ndna", Arrays.asList("Not Available", "Not Applicable"), writer, Locale.ENGLISH, DEFAULT);
cell.addElement(group);
PdfPTable table = new PdfPTable(1);
table.addCell(cell);
cell = new PdfPCell();
cell.setCellEvent(new ActionEvent(writer, "http://localhost:8080/entrypointpdf"));
table.addCell(cell);
document.add(table);
group.addAnnotations();
document.close();
}
这是 Action 事件
class ActionEvent implements PdfPCellEvent {
private PdfWriter writer;
private String submissionUrl;
public ActionEvent(PdfWriter writer, String submissionUrl) {
this.writer = writer;
this.submissionUrl = submissionUrl;
}
@Override
public void cellLayout(PdfPCell cell, Rectangle position, PdfContentByte[] canvases) {
PushbuttonField submit = new PushbuttonField(writer, position, "submit") {
@Override
public PdfFormField getField() throws IOException, DocumentException {
PdfFormField field = super.getField();
field.setAction(PdfAction.createSubmitForm(submissionUrl, null, 0));
return field;
}
};
submit.setText("CLICK ME");
submit.setTextColor(BaseColor.BLUE);
submit.setFont(DEFAULT.getCalculatedBaseFont(false));
submit.setVisibility(PushbuttonField.VISIBLE);
try {
writer.addAnnotation(submit.getField());
} catch (Exception ignore) {
}
}
}
这是 PdfRadioGroupTable
public class PdfRadioGroupTable extends PdfPTable {
private PdfWriter writer;
public PdfFormField radioGroup;
public PdfRadioGroupTable(String name, List<String> choices, PdfWriter writer, Locale locale, Font font) {
super(2);
this.writer = writer;
setWidthPercentage(100);
try {
setTotalWidth(new float[] { 14, 400 });
} catch (DocumentException ignore) {
}
radioGroup = PdfFormField.createRadioButton(writer, true);
radioGroup.setFieldName(name);
PdfPCell cell;
for (String choice : choices) {
cell = new PdfPCell();
cell.setBorder(0);
cell.setPaddingBottom(5);
cell.setUseAscender(true);
cell.setUseDescender(true);
cell.setVerticalAlignment(PdfPCell.ALIGN_CENTER);
cell.setCellEvent(new RadioCellEvent(radioGroup, choice));
addCell(cell);
cell = new PdfPCell();
cell.setBorder(0);
cell.setPaddingBottom(5);
cell.setPaddingLeft(6);
cell.setUseAscender(true);
cell.setUseDescender(true);
cell.setVerticalAlignment(PdfPCell.ALIGN_CENTER);
cell.addElement(new Phrase(choice), font));
addCell(cell);
}
}
class RadioCellEvent implements PdfPCellEvent {
protected PdfFormField radioGroup;
protected String value;
public RadioCellEvent(PdfFormField radioGroup, String value) {
this.radioGroup = radioGroup;
this.value = value;
}
@Override
public void cellLayout(PdfPCell cell, Rectangle position, PdfContentByte[] canvases) {
RadioCheckField radio = new RadioCheckField(writer, position, null, value);
radio.setChecked(false);
radio.setBorderColor(GrayColor.GRAYBLACK);
radio.setBackgroundColor(GrayColor.GRAYWHITE);
radio.setCheckType(RadioCheckField.TYPE_CIRCLE);
try {
PdfFormField field = radio.getRadioField();
writer.addAnnotation(field);
radioGroup.addKid(field);
} catch (Exception exception) {
throw new ExceptionConverter(exception);
}
}
}
}
以下是当单击 pdf 中的按钮(在 acrobat 中)时服务器端发生的情况:
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "inline; filename=\"your.pdf\"");
try {
FdfReader fdf = new FdfReader(request.getInputStream());
File pdfFile = new File("/test.pdf");
InputStream is = new FileInputStream(pdfFile);
PdfReader reader = new PdfReader(is);
File resultFile = new File(System.currentTimeMillis() + "_" + pdfFile.getName());
FileOutputStream out = new FileOutputStream(resultFile);
PdfStamper stamper = new PdfStamper(reader, out);
AcroFields fields = stamper.getAcroFields();
fields.setFields(fdf);
// EXTRACT VALUES HERE
stamper.setFormFlattening(true);
stamper.close();
reader.close();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bos.write(FilesUtilities.read(resultFile));
OutputStream os = response.getOutputStream();
bos.writeTo(os);
os.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
所以基本上我生成了一个带有一个单选组和一个按钮的 pdf 文件。该按钮导致 pdf 字段被导入,其想法是以先前生成的 pdf 的形式将“收据”发送回用户,其中包含与用户选择/值和导入状态字段相同的字段(正常、丢失、错误数据等)(我在上面的代码中省略了该部分,因为该部分工作正常)。我的问题是,返回的 pdf 中的单选字段看起来与原始 pdf 中的可编辑字段完全不同(它们甚至不再看起来像单选按钮)。
我尝试使用
fields.setFieldProperty("ndna", "setfflags", PdfFormField.FF_READ_ONLY, null);
并通过此禁用表单展平会导致返回的 pdf 中出现相同的替代外观。
非常感谢您的帮助,因为我已经为此苦苦挣扎了一段时间......
安东尼
最佳答案
这似乎是某些版本的 iText 上的错误。我在 iTextSharp 5.5.5 版本中遇到了同样的问题,升级到 5.5.9 版本后解决了。我用“nuget”来做到这一点。这是一个链接:https://www.nuget.org/packages/iTextSharp/5.5.9
关于java - 使用 iText 的 pdf 交互式表单的外观问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32906739/