Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Create a Radio Button Group with PDFBox 2.0

Tags:

java

pdfbox

I want to create a Radio Button group using PDFBox 2.0, I am able to create 3 Radio Buttons, but I can't figure out how to group them (PDFBox 1.8, used PDRadioCollection, but 2.0 doesn't.).

How do you create a Radio Button Group with PDFBox 2.0?

Here is my current code:

        PDDocument document = new PDDocument();
        PDPage page = new PDPage(PDRectangle.A4);
        document.addPage(page);

        PDAcroForm acroForm = new PDAcroForm(document);
        acroForm.setNeedAppearances(true);
        document.getDocumentCatalog().setAcroForm(acroForm);

        PDResources res = new PDResources();
        COSName fontName = res.add(PDTrueTypeFont.load(document, new FileInputStream("C:/Windows/Fonts/arial.ttf"), StandardEncoding.INSTANCE));
        acroForm.setDefaultResources(res);
        acroForm.setDefaultAppearance('/' + fontName.getName() + " 10 Tf 0 g");

        PDPageContentStream contents = new PDPageContentStream(document, page);

        List<String> options = Arrays.asList("a", "b", "c");
        for (int i = 0; i < options.size(); i++) {
            PDRadioButton button = new PDRadioButton(acroForm);
            button.setPartialName("RadioButton" + options.get(i));

            PDAppearanceCharacteristicsDictionary fieldAppearance = new PDAppearanceCharacteristicsDictionary(new COSDictionary());
            fieldAppearance.setBorderColour(new PDColor(new float[]{0, 0, 0}, PDDeviceRGB.INSTANCE));

            PDAnnotationWidget widget = button.getWidgets().get(0);
            widget.setRectangle(new PDRectangle(30, 800 - i * (21), 16, 16));
            widget.setAppearanceCharacteristics(fieldAppearance);

            acroForm.getFields().add(button);
            page.getAnnotations().add(widget);
        }
        contents.close();
        document.save(new FileOutputStream("RadioButtonTest.pdf"));
        document.close();
like image 233
Adz Avatar asked Jan 19 '16 01:01

Adz


People also ask

What is Radio Group Java?

android.widget.RadioGroup. This class is used to create a multiple-exclusion scope for a set of radio buttons. Checking one radio button that belongs to a radio group unchecks any previously checked radio button within the same group. Intially, all of the radio buttons are unchecked.

Is PDFBox thread safe?

Is PDFBox thread safe? No! Only one thread may access a single document at a time. You can have multiple threads each accessing their own PDDocument object.


1 Answers

By looking at Tilman suggestions and by general fluke, I was able to come up with, what looks like, a solution to creating a radio button group.

note: I have been verifying my results by checking the pdf in Acrobat 11.

here is the code:

try {
        PDDocument document = new PDDocument();
        PDPage page = new PDPage(PDRectangle.A4);

        document.addPage(page);

        PDAcroForm acroForm = new PDAcroForm(document);
        acroForm.setNeedAppearances(true);
        acroForm.setXFA(null);
        document.getDocumentCatalog().setAcroForm(acroForm);

        PDFont font = PDType1Font.HELVETICA;

        PDResources res = new PDResources();
        COSName fontName = res.add(font);
        acroForm.setDefaultResources(res);
        acroForm.setDefaultAppearance('/' + fontName.getName() + " 10 Tf 0 g");

        PDPageContentStream contents = new PDPageContentStream(document, page);

        List<String> options = Arrays.asList("a", "b", "c");
        PDRadioButton radioButton = new PDRadioButton(acroForm);
        radioButton.setPartialName("RadioButtonParent");
        radioButton.setExportValues(options);
        radioButton.getCOSObject().setName(COSName.DV, options.get(1));

        List<PDAnnotationWidget> widgets = new ArrayList<>();
        for (int i = 0; i < options.size(); i++) {

            PDAppearanceCharacteristicsDictionary fieldAppearance = new PDAppearanceCharacteristicsDictionary(new COSDictionary());
            fieldAppearance.setBorderColour(new PDColor(new float[]{0, 0, 0}, PDDeviceRGB.INSTANCE));

            PDAnnotationWidget widget = new PDAnnotationWidget();
            widget.setRectangle(new PDRectangle(30, 811 - i * (21), 16, 16));
            widget.setAppearanceCharacteristics(fieldAppearance);

            widgets.add(widget);
            page.getAnnotations().add(widget);

            // added by Tilman on 13.1.2017, without it Adobe does not set the values properly
            PDAppearanceDictionary appearance = new PDAppearanceDictionary();
            COSDictionary dict = new COSDictionary();
            dict.setItem(COSName.getPDFName("Off"), new COSDictionary());
            dict.setItem(COSName.getPDFName(options.get(i)), new COSDictionary());
            PDAppearanceEntry appearanceEntry = new PDAppearanceEntry(dict);
            appearance.setNormalAppearance(appearanceEntry);
            widget.setAppearance(appearance);


            contents.beginText();
            contents.setFont(font, 10);
            contents.newLineAtOffset(56, 811 - i * (21) + 4);
            contents.showText(options.get(i));
            contents.endText();
        }
        radioButton.setWidgets(widgets);
        acroForm.getFields().add(radioButton);

        contents.close();
        try(FileOutputStream output = new FileOutputStream("Test.pdf")) {
            document.save(output);
        }
        document.close();
    } catch (IOException e) {
        e.printStackTrace();
    }

The key seems to be setting the partial names of each radio button the the same value, but I can't say for sure.

Update 17.1.2019: I am the "Tilman" mentioned at the beginning, and have created a more flexible code for radio buttons and uploaded it into the source code repository. It has the advantage that it creates the appearance streams similar to Adobe, so it is no longer needed to call acroForm.setNeedAppearances(true);. The code works with PDFBox 2.0.13 and higher.

like image 122
Adz Avatar answered Sep 29 '22 07:09

Adz