Как установить границу для флажка AppesionStream с помощью pdfbox 2 - PullRequest
0 голосов
/ 16 мая 2019

Я использую PDFBox v2 для создания PDF с нуля, у меня проблема с появлением флажка, когда флажок установлен (и мышь не нажата), граница флажка не отображается.

Я использовал пример кода, предоставленный Тилманом на официальном документе, для создания кнопок радио и настройки его для создания флажка:

public void drawCheckBox() throws IOException {
    for (Entry<String, List<InputCheckBox>> entry : myHash.entrySet()) {
        String checkBoxKey = entry.getKey(); // radio buton key
        List<InputCheckBox> checkBoxValue = entry.getValue(); // checkbox list(s)
        PDCheckBox checkBox = new PDCheckBox(checkBoxValue.get(0).getAcroForm());
        checkBox.setPartialName(checkBoxKey);
        checkBox.setExportValues(Arrays.asList(checkBoxKey));

        // couleur de la checkbox
        PDAppearanceCharacteristicsDictionary appearanceCharacteristics = new PDAppearanceCharacteristicsDictionary(
                new COSDictionary());
        appearanceCharacteristics.setBorderColour(new PDColor(new float[] { 0, 0, 0 }, PDDeviceRGB.INSTANCE));
        appearanceCharacteristics.setBackground(new PDColor(new float[] { 1, 1, 1 }, PDDeviceRGB.INSTANCE));

        checkBoxValue.get(0).getAcroForm().getFields().add(checkBox);
        List<PDAnnotationWidget> widgets = new ArrayList<>();
        for (int i = 0; i < checkBoxValue.size(); i++) {
            PDAnnotationWidget widget = new PDAnnotationWidget();
            widget.setRectangle(new PDRectangle(checkBoxValue.get(i).getLeft(),
                    checkBoxValue.get(i).getPage().getMediaBox().getHeight()
                            - (checkBoxValue.get(i).getTop() + checkBoxValue.get(i).getHeight()),
                    checkBoxValue.get(i).getWidth(), checkBoxValue.get(i).getHeight()));

            // border du checkbox
            widget.setAppearanceCharacteristics(appearanceCharacteristics);
            PDBorderStyleDictionary borderStyleDictionary = new PDBorderStyleDictionary();
            borderStyleDictionary.setWidth(1);
            borderStyleDictionary.setStyle(PDBorderStyleDictionary.STYLE_SOLID);
            // creer les apparence de radio button pour l'état off et l'état activé
            COSDictionary apNDict = new COSDictionary();
            apNDict.setItem(COSName.Off,
                    createCheckBoxAppearanceStream(checkBoxValue.get(i).getDocument(), widget, false));
            apNDict.setItem(COSName.ON,
                    createCheckBoxAppearanceStream(checkBoxValue.get(i).getDocument(), widget, true));

            PDAppearanceDictionary appearance = new PDAppearanceDictionary();
            PDAppearanceEntry appearanceNEntry = new PDAppearanceEntry(apNDict);
            appearance.setNormalAppearance(appearanceNEntry);
            // appliquer l'apparence dans le widget
            widget.setBorderStyle(borderStyleDictionary);
            widget.setPage(checkBoxValue.get(i).getPage());
            widget.setAppearance(appearance);
            widget.setParent(checkBox);
            widget.setAppearanceState("Off");
            // widget.setAnnotationName(key);
            widget.setPrinted(true);
            checkBoxValue.get(i).getPage().getAnnotations().add(widget);
            widgets.add(widget);
            checkBox.setWidgets(widgets);
        }
    }
}

// les methodes ci_dessous sert a creer l'apparence des checkBox selon leur
// état coché ou non
private static PDAppearanceStream createCheckBoxAppearanceStream(final PDDocument document,
        PDAnnotationWidget widget, boolean on) throws IOException {
    PDRectangle rect = widget.getRectangle();
    PDAppearanceStream onAP = new PDAppearanceStream(document);
    onAP.setResources(new PDResources());
    onAP.setBBox(new PDRectangle(rect.getWidth(), rect.getHeight()));
    PDPageContentStream onAPCS = new PDPageContentStream(document, onAP);

    PDAppearanceCharacteristicsDictionary appearanceCharacteristics = widget.getAppearanceCharacteristics();
    PDColor backgroundColor = appearanceCharacteristics.getBackground();
    PDColor borderColor = appearanceCharacteristics.getBorderColour();
    float lineWidth = getLineWidth(widget);
    onAPCS.setLineWidth(lineWidth);
    onAPCS.setNonStrokingColor(backgroundColor);
    onAPCS.fill();
    onAPCS.setStrokingColor(borderColor);
    onAPCS.stroke();

    if (on) {
        onAPCS.setFont(PDType1Font.ZAPF_DINGBATS, 14.5f);
        onAPCS.beginText();
        onAPCS.newLineAtOffset(0, 0);
        onAPCS.showText("\u2714");
        onAPCS.endText();
        onAPCS.fill();
    }

    onAPCS.close();
    return onAP;
}

static float getLineWidth(PDAnnotationWidget widget) {
    PDBorderStyleDictionary bs = widget.getBorderStyle();
    if (bs != null) {
        return bs.getWidth();
    }
    return 1;
}

вот результат, который я получаю:

here is the result that i'am getting

и вот что я должен иметь:

and here is what i am supposed to have

1 Ответ

1 голос
/ 16 мая 2019

Вы выполняете заполнение и обводку пути без определения пути до:

onAPCS.setNonStrokingColor(backgroundColor);
onAPCS.fill();
onAPCS.setStrokingColor(borderColor);
onAPCS.stroke();

Попробуйте вместо этого определить путь (в виде прямоугольника):

onAPCS.setNonStrokingColor(backgroundColor);
onAPCS.setStrokingColor(borderColor);
onAPCS.addRect(0, 0, rect.getWidth(), rect.getHeight());
onAPCS.fillAndStroke();

(Или выВозможно, вы захотите использовать прямоугольник чуть меньшего размера, например, onAPCS.addRect(1, 1, rect.getWidth() - 2, rect.getHeight() - 2).)


В качестве отступа, далее вниз вы снова используете fill, на этот раз без какой-либо очевидной причины:

if (on) {
    ...
    onAPCS.endText();
    onAPCS.fill();
}

Вы должны удалить это fill, поскольку оно, строго говоря, даже недействительно: fill и stroke разрешены только сразу после определения пути!

...