Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Checkboxes are "checked" when pressing only one of them #121

Closed
rogeralmengor opened this issue Jul 21, 2022 · 8 comments
Closed

Checkboxes are "checked" when pressing only one of them #121

rogeralmengor opened this issue Jul 21, 2022 · 8 comments

Comments

@rogeralmengor
Copy link

I add a series of checkboxes within the cells of table.
The problem is: When I checked one, all of them got checked. Is there a way to make them independent to each other?

from re import A, I
from borb.pdf.document.document import Document
from borb.pdf.page.page import Page
from borb.pdf.pdf import PDF
from borb.pdf.canvas.layout.page_layout.multi_column_layout import SingleColumnLayout
from borb.pdf.canvas.layout.page_layout.page_layout import PageLayout
import geopandas as gpd
from borb.pdf.canvas.layout.table.fixed_column_width_table import FixedColumnWidthTable
from borb.pdf.canvas.layout.text.paragraph import Paragraph
from borb.pdf.canvas.layout.forms.text_field import TextField
from borb.pdf.canvas.color.color import HexColor
from decimal import Decimal
from borb.pdf.canvas.layout.layout_element import Alignment
from borb.pdf.canvas.layout.forms.drop_down_list import DropDownList
# New import(s)
from borb.pdf.pdf import PDF
import pandas as pd
import shapely
import folium
from shapely import wkt
from shapely.geometry import box 
import matplotlib.pyplot as plt
#from PIL import Image
from borb.pdf.canvas.layout.image.barcode import Barcode, BarcodeType  
from borb.pdf.canvas.layout.layout_element import LayoutElement
from borb.pdf.canvas.layout.table.flexible_column_width_table import FlexibleColumnWidthTable
from borb.pdf.canvas.layout.image.image import Image
import logging
import random 


layout.add(Paragraph("Stammdaten:", font="Helvetica-Bold", font_size=10))
layout.add(Paragraph(
        "Prüfbemerkungen Amt: ",
        font = "Helvetica-Bold", font_size=10, border_bottom=False,border_right=False,
        padding_bottom=Decimal(0.5),
        margin_bottom= Decimal(0.5,)))

    from borb.pdf.canvas.layout.forms.check_box import CheckBox
    from borb.pdf.canvas.layout.table.table import  TableCell

    table2: FixedColumnWidthTable = FixedColumnWidthTable(number_of_rows=2, number_of_columns=4)
    table2.add(Paragraph("bestätig  ", horizontal_alignment=Alignment.LEFT, font_color=HexColor("464E51"), font_size=8))
    table2.add(TableCell(CheckBox(font_color=HexColor("464E51"))))
    #table2.add(Paragraph("  ", horizontal_alignment=Alignment.LEFT, font_color=HexColor("464E51"), font_size=8))
    table2.add(Paragraph("Erfassung in profil c/s", horizontal_alignment=Alignment.LEFT, font_color=HexColor("464E51"), font_size=8))
    table2.add(CheckBox(font_color=HexColor("464E51")))
    #table2.add(Paragraph("  ", horizontal_alignment=Alignment.LEFT, font_color=HexColor("464E51"), font_size=8))
    table2.add(Paragraph("nicht bestätig  ", horizontal_alignment=Alignment.LEFT, font_color=HexColor("464E51"), font_size=8))
    table2.add(CheckBox(font_color=HexColor("464E51")))
    #table2.add(Paragraph("  ", horizontal_alignment=Alignment.LEFT, font_color=HexColor("464E51"), font_size=8))
    table2.add(Paragraph("Nachweiß:", horizontal_alignment=Alignment.LEFT, font_color=HexColor("464E51"), font_size=8))
    table2.add(CheckBox(font_color=HexColor("464E51")))
    #table2.add(Paragraph("  ", horizontal_alignment=Alignment.LEFT, font_color=HexColor("464E51"), font_size=8))
    table2.set_padding_on_all_cells(Decimal(5), Decimal(5), Decimal(5), Decimal(5))
    table2.no_borders()
    layout.add(table2) 

I expected one checkbox activated at the time I clicked on it.

Bug_checkbox

  • OS: Windows
  • borb version [e.g. 22]
@jorisschellekens
Copy link
Owner

Hi,

I think your problem is related to a similar issue (recently solved).
borb performs some optimisations when storing a PDF, it hashes every object, and whenever an object is stored (that has a known hash value) it just references the previously stored object.

That means the checkboxes get a reference to the same appearance dictionary, which is probably why you get this rendering issue.

The related issue was similar behaviour with a TextField.

Can you create a small, minimal example (two checkboxes on a page)?
Then I can run my fix against your code.

@rogeralmengor
Copy link
Author

Hi @jorisschellekens!

Thank you very much for your reply!,
Below it's a small reproducible example with check boxes.
I hope it suffice to check it out against your fix.

Kind Regards,

Roger

from borb.pdf.document.document import Document
from borb.pdf.page.page import Page
from borb.pdf.canvas.layout.page_layout.multi_column_layout import SingleColumnLayout
from borb.pdf.canvas.layout.page_layout.page_layout import PageLayout
from borb.pdf.canvas.layout.table.fixed_column_width_table import FixedColumnWidthTable
from borb.pdf.canvas.layout.text.paragraph import Paragraph
from borb.pdf.pdf import PDF
from borb.pdf.canvas.layout.forms.check_box import CheckBox 
from decimal import Decimal

# Create empty Document
pdf = Document()

page = Page()

pdf.add_page(page)

layout: PageLayout = SingleColumnLayout(page)

layout.add(Paragraph("Question: Do you own a pet?", font="Helvetica-Bold", font_size=8))

table: FixedColumnWidthTable = FixedColumnWidthTable(number_of_rows=2, number_of_columns=2)

table.add(Paragraph("Yes?"))
table.add(CheckBox())
table.add(Paragraph("No?"))
table.add(CheckBox())
table.no_borders()
table.set_padding_on_all_cells(Decimal(5), Decimal(5), Decimal(5), Decimal(5))

layout.add(table)


out_pdf_file_name = "checkbox_example.pdf"
with open(out_pdf_file_name, "wb") as out_file_handle:
    PDF.dumps(out_file_handle, pdf)

@jorisschellekens
Copy link
Owner

Can you verify whether this PDF displays the expected behaviour?

checkbox_example.pdf

Kind regards,
Joris Schellekens

@rogeralmengor
Copy link
Author

Hi,

I opened the pdf, and still both checkboxes are checked at the same time when I just click on one of them.

@kbrown01
Copy link

kbrown01 commented Oct 5, 2022

Personally to me that code looks wrong. You are just adding doing:

table.add(CheckBox())

I would think you need to add at least a qualifier to what the field name is for the checkbox. Otherwise the code treats the name as 'None' and since they all have the same name, they all behave the same way. The code to me is:

    def __init__(
        self,
        font_size: Decimal = Decimal(12),
        font_color: Color = HexColor("000000"),
        field_name: typing.Optional[str] = None,
    ):

In other PDF tools you always associate a name with a field so it can be treated separately. And that code is not associating different names to fields (like with some GUID) if you do not enter a name.

Something like (untested):

table.add(Paragraph("Yes?"))
table.add(CheckBox(field_name="checkbox_1_yes"))
table.add(Paragraph("No?"))
table.add(CheckBox(field_name="checkbox_1_no"))

@jorisschellekens
Copy link
Owner

If you do not enter a name, borb will auto-generate one (based on the number of fields on the Page).

I think the problem is something a bit deeper. You see, borb tries to optimize the PDF when it is being written. So whenever it detects some data that is duplicate, it writes it only once and the second time it uses a reference.

Although the PDF spec does not forbid it, this seems to be a problem for some PDF reader software. I remember a similar bug with a TextField.

I then added the option to tell the IO module that an object (regardless of its similarity) should be treated as being unique.

I guess (hope) this bug will be something similar.

That being said, I am going to rework some of the FormField logic, so that it fits better in the general LayoutElement framework. I will of course try to tackle this bug while I'm in that part of the code.

Kind regards,
Joris Schellekens

@kbrown01
Copy link

kbrown01 commented Oct 8, 2022

Well I could be wrong,I looked at that code too. It seems to generate a name that would be the same for everything on a page. The names must be unique.

@jorisschellekens
Copy link
Owner

I added a test to verify that 2 checkboxes do in fact get unique names.
I output a PDF with 2 checkboxes and opened it in Adobe Reader on my phone (Adobe is not supported on Linux), and both checkboxes work independently from eachother. So that seems to work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants