Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
554 views
in Technique[技术] by (71.8m points)

java - How to Create a Radio Button Group with PDFBox 2.0

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();
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...