如何在PDF BOX中创建一个按钮?

7
我想在PDFBOX中创建一个按钮,即验证或重置按钮,它将调用PDF中嵌入的javascript的某些函数。
我该如何在PDFBOX中创建这样的按钮?
我已经尝试了PDPushButton片段的以下代码,但它无法正常工作。在此处当我单击按钮区域时,就会显示勾号符号并在每次单击时切换。而且边框没有显示出来。 相反,我想要显示一个带有标签和边框的普通按钮。
我正在使用pdfbox版本1.8.10。
PDDocument doc = new PDDocument();
PDPage page = new PDPage();
doc.addPage(page);            

PDAcroForm acroForm = new PDAcroForm(doc);
        doc.getDocumentCatalog().setAcroForm(acroForm);

        PDActionJavaScript javascript = new PDActionJavaScript("function validate(index){ app.alert(index); }");
        doc.getDocumentCatalog().setOpenAction( javascript );

COSDictionary cosDict = new COSDictionary();
            COSArray rect = new COSArray();
            rect.add(new COSFloat(100));
            rect.add(new COSFloat(10));
            rect.add(new COSFloat(200));
            rect.add(new COSFloat(60));

            cosDict.setItem(COSName.RECT, rect);
            cosDict.setItem(COSName.FT, COSName.getPDFName("Btn")); // Field Type
            cosDict.setItem(COSName.TYPE, COSName.ANNOT);
            cosDict.setItem(COSName.SUBTYPE, COSName.getPDFName("Widget"));
            cosDict.setItem(COSName.T, new COSString("My Btn"));
            cosDict.setItem(COSName.V, new COSString("Validate"));
            cosDict.setItem(COSName.DA, new COSString("/Helv 7 Tf 0 g"));

            PDPushButton button = new PDPushButton(acroForm, cosDict);
            button.setValue("Validate Button");

            PDActionJavaScript tfJs = new PDActionJavaScript("validate("+index+");");
            PDAnnotationAdditionalActions tfAction = new PDAnnotationAdditionalActions();
            tfAction.setU(tfJs);
            button.getWidget().setActions(tfAction);

            PDGamma colourBlack = new PDGamma();
            PDAppearanceCharacteristicsDictionary fieldAppearance = 
                    new PDAppearanceCharacteristicsDictionary(cosDict);
            fieldAppearance.setBorderColour(colourBlack);
            button.getWidget().setAppearanceCharacteristics(fieldAppearance);

            page.getAnnotations().add(button.getWidget());

            acroForm.getFields().add(button);

我已经尝试使用PDPushButton,但我无法在此处设置按钮文本值,而且当我单击按钮时,勾号符号会切换。 - Nirav Patel
1
尽管我找到了它(你的代码不是自动运行的,文档和页面丢失),但我无法看到任何东西。请将以下内容添加到您的代码中:cosDict.setInt(COSName.FF, 65536); 这是按钮的标志。 - Tilman Hausherr
将 new PDAppearanceCharacteristicsDictionary(cosDict) 更改为 new PDAppearanceCharacteristicsDictionary(new COSDictionary())。 - Tilman Hausherr
@Tilman 感谢您对添加代码cosDict.setInt(COSName.FF, 65536)的建议; 这个方法有效了,但是在设定按钮边框时仍然有问题。 使用new PDAppearanceCharacteristicsDictionary(new COSDictionary())并没有奏效。 - Nirav Patel
1
我所做的是(在开始时)COSDictionary acroFormDict = new COSDictionary(); acroFormDict.setBoolean(COSName.getPDFName("NeedAppearances"), false); acroFormDict.setItem(COSName.getPDFName("Fields"), new COSArray()); PDAcroForm acroForm = new PDAcroForm(doc, acroFormDict); doc.getDocumentCatalog().setAcroForm(acroForm); - Tilman Hausherr
显示剩余2条评论
2个回答

5
以下代码生成了带有边框的适当按钮,并正确调用了JavaScript函数。唯一的问题是在按钮上设置验证标签。如果有人有解决方法,请提供反馈。
PDDocument doc = new PDDocument();
        PDPage page = new PDPage();
        doc.addPage(page);   

        COSDictionary acroFormDict = new COSDictionary(); 
        acroFormDict.setBoolean(COSName.getPDFName("NeedAppearances"), true);
        acroFormDict.setItem(COSName.getPDFName("Fields"), new COSArray());

        PDAcroForm acroForm = new PDAcroForm(doc, acroFormDict);
        doc.getDocumentCatalog().setAcroForm(acroForm);

        PDActionJavaScript javascript = new PDActionJavaScript("function validate(index){ app.alert(index); }");
        doc.getDocumentCatalog().setOpenAction( javascript );

        COSDictionary cosDict = new COSDictionary();
        COSArray rect = new COSArray();
        rect.add(new COSFloat(100));
        rect.add(new COSFloat(10));
        rect.add(new COSFloat(200));
        rect.add(new COSFloat(60));


        cosDict.setItem(COSName.RECT, rect);
        cosDict.setItem(COSName.FT, COSName.getPDFName("Btn")); // Field Type
        cosDict.setItem(COSName.TYPE, COSName.ANNOT);
        cosDict.setItem(COSName.SUBTYPE, COSName.getPDFName("Widget"));
        cosDict.setItem(COSName.T, new COSString("Btn"+1));
        cosDict.setItem(COSName.V, new COSString("Validate"));
        cosDict.setItem(COSName.DA, new COSString("/Helv 7 Tf 0 g"));
        cosDict.setInt(COSName.FF, 65536); 

        PDPushButton button = new PDPushButton(acroForm, cosDict);
        button.setValue("Validate Button");

        PDActionJavaScript tfJs = new PDActionJavaScript("validate("+1+");");
        PDAnnotationAdditionalActions tfAction = new PDAnnotationAdditionalActions();
        tfAction.setU(tfJs);
        button.getWidget().setActions(tfAction);

        PDGamma colourBlack = new PDGamma();
        PDAppearanceCharacteristicsDictionary fieldAppearance = 
                new PDAppearanceCharacteristicsDictionary(new COSDictionary());
        fieldAppearance.setBorderColour(colourBlack);
        button.getWidget().setAppearanceCharacteristics(fieldAppearance);

        page.getAnnotations().add(button.getWidget());

        acroForm.getFields().add(button);

         doc.save("/path");
         doc.close();

1
缺少文本的原因可能是没有外观流。这是一个类似于页面内容流的流,但用于表单对象。最好使用PDFDebugger将您的文件与具有此类按钮的另一个PDF文件进行比较(例如https://issues.apache.org/jira/browse/PDFBOX-2203中的文件)。该字段位于对象51中,外观流位于对象52中。 - Tilman Hausherr
12.7.4.2.2 按钮 一个按钮字段应该有一个Btn的字段类型,并将Pushbutton标志(见表226)设置为1。因为这种类型的按钮不保留任何永久值,所以它不应使用字段字典中的V和DV条目(见表220)。 - Tilman Hausherr
@Tilman,我检查了 issues.apache.org/jira/browse/PDFBOX-2203 上的按钮示例pdf。 在调试此PDF之后,我发现它在内部使用字段类型Tx用于文本框,而不是Btn用于按钮。 根据此修改代码后,解决方案可以正常工作。 - Nirav Patel

3
以下是“如何在PDFBox 2.0.0中为PDPushButton设置标题”的解决方案:
要显示pushbutton的标题值,您需要调用PDAppearanceCharacteristicsDictionary的setNormalCaption(“captionStr”)。 下面是带有文本颜色更改的按钮标题值的代码:
    PDDocument doc = new PDDocument();
    PDPage page = new PDPage();
    doc.addPage(page);

    try {
        COSDictionary acroFormDict = new COSDictionary();
        acroFormDict.setBoolean(COSName.getPDFName("NeedAppearances"), true);
        acroFormDict.setItem(COSName.FIELDS, new COSArray());

        PDAcroForm acroForm = new PDAcroForm(doc, acroFormDict);
        doc.getDocumentCatalog().setAcroForm(acroForm);

        PDActionJavaScript javascript = new PDActionJavaScript(
                "function validate(index){ app.alert(index); }");
        doc.getDocumentCatalog().setOpenAction(javascript);

        COSDictionary cosDict = new COSDictionary();
        COSArray rect = new COSArray();
        rect.add(new COSFloat(50));
        rect.add(new COSFloat(775));
        rect.add(new COSFloat(100));
        rect.add(new COSFloat(750));
        cosDict.setItem(COSName.RECT, rect);
        cosDict.setItem(COSName.FT, COSName.getPDFName("Btn"));
        cosDict.setItem(COSName.TYPE, COSName.ANNOT);
        cosDict.setItem(COSName.SUBTYPE, COSName.getPDFName("Widget"));
        cosDict.setItem(COSName.T, new COSString("ClickMe"));
        //cosDict.setItem(COSName.V, new COSString("Click Me"));
        cosDict.setItem(COSName.DA, new COSString("/F0 6 Tf 0 g 1 1 1 rg "));

        PDPushButton button = new PDPushButton(acroForm);

        PDActionJavaScript tfJs = new PDActionJavaScript("validate("+1+");");
        PDAnnotationAdditionalActions tfAction = new PDAnnotationAdditionalActions();
        tfAction.setU(tfJs);
        button.getWidgets().get(0).setActions(tfAction);

    //  button.setReadOnly(true);
        button.getCOSObject().addAll(cosDict);
        acroForm.getFields().add(button);

        PDAnnotationWidget widget = button.getWidgets().get(0);

        PDAppearanceCharacteristicsDictionary fieldAppearance = 
                new PDAppearanceCharacteristicsDictionary(new COSDictionary());
        COSArray borderColorArray = new COSArray();
        borderColorArray.add(new COSFloat((float) (141f/255f)));
        borderColorArray.add(new COSFloat((float) (179f/255f)));
        borderColorArray.add(new COSFloat((float) (226f/255f)));
        PDColor blue = new PDColor(borderColorArray, PDDeviceRGB.INSTANCE);
        fieldAppearance.setBorderColour(blue);
        fieldAppearance.setBackground(blue);
        fieldAppearance.setNormalCaption("Click Me");

        widget.setAppearanceCharacteristics(fieldAppearance);
        page.getAnnotations().add(widget);


        File file = new File("/path");
        System.out.println("File created");
        FileOutputStream fOut = new FileOutputStream(file);
        doc.save(fOut);
        doc.close();
    } catch (IOException e) {
        e.printStackTrace();
    }

Here:

cosDict.setItem(COSName.V, new COSString("Click Me")); 

并且在这里:

button.setValue("Click Me");

无法工作。

为此,您需要添加以下行:

fieldAppearance.setNormalCaption("Click Me");

上述示例是PDFBox2.0的解决方案。
在PDFBox 1.8.11中,我认为这也将起作用。 :)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接