You should assume the habit to only use True or False when setting values of radio buttons.
Definitely only False for the Off-state.
The possible values for buttons (radio or checkbox) are enumerated by function Widget.button_states(). Here are the responses for those 2 buttons:
btn1.button_states()
{'normal': ['Off', 'Choice1'], 'down': None}
btn2.button_states()
{'normal': ['Off', 'Choice2'], 'down': None}
The name of the “On” state of a button can be found out by
btn2.on_state()
'Choice2'
btn1.on_state()
'Choice1'
Setting a button to “On”, the statement btn.field_value = btn.on_state() should also work (instead of using True).
So much for the theory.
Here is the state of the file after open:
doc=pymupdf.open(doc.name)
page=doc[0]
btn1=page.load_widget(111)
btn2=page.load_widget(112)
btn1.field_value
'Off'
btn2.field_value
'Choice2'
# print the PDF objects, including their parent field (xref=63)
print(doc.xref_object(63))
<<
/DA (/ZaDb 0 Tf 0 g)
/FT /Btn
/Ff 49152
/Kids [ 111 0 R 112 0 R ]
/T (RadioGroup)
/V /Choice2
>>
print(doc.xref_object(111))
<<
/AP <<
/D <<
/Choice1 75 0 R
/Off 76 0 R
>>
/N <<
/Choice1 73 0 R
/Off 74 0 R
>>
>>
/AS /Off
/BS <<
/S /I
/W 1
>>
/F 4
/MK <<
/BC [ 0 ]
/BG [ 1 ]
>>
/P 69 0 R
/Parent 63 0 R
/Rect [ 42.5456 693.665 60.5456 711.665 ]
/Subtype /Widget
/Type /Annot
>>
print(doc.xref_object(112))
<<
/AP <<
/D <<
/Choice2 79 0 R
/Off 80 0 R
>>
/N <<
/Choice2 77 0 R
/Off 78 0 R
>>
>>
/AS /Choice2
/BS <<
/S /I
/W 1
>>
/F 4
/MK <<
/BC [ 0 ]
/BG [ 1 ]
>>
/P 69 0 R
/Parent 63 0 R
/Rect [ 42.5456 668.792 60.5456 686.792 ]
/Subtype /Widget
/Type /Annot
>>
Everything looks as it should!
- parent shows
/V = /Choice2
- btn2 shows
/AS = /Choice2
- btn1 shows
/AS = /Off.
Now set btn1 to selected and update it!
btn1.field_value=btn1.on_state()
btn1.field_value
'Choice1'
btn1.update() #<=== this is a MUST DO
print(doc.xref_object(111))
<<
/AP <<
/N <<
/Off 152 0 R
/Choice1 153 0 R
>>
>>
/AS /Choice1 #<=== this has changed as expected
/BS <<
/S /I
/W 1
>>
/F 4
/MK <<
/BC [ 0 ]
/BG [ 1 ]
>>
/P 69 0 R
/Parent 63 0 R
/Rect [ 42.5456 693.665 60.5456 711.665 ]
/Subtype /Widget
/Type /Annot
/DA (0 g /ZaDb 0 Tf)
/Ff 49152
>>
print(doc.xref_object(63)) #<=== look at the parent
<<
/DA (/ZaDb 0 Tf 0 g)
/FT /Btn
/Ff 49152
/Kids [ 111 0 R 112 0 R ]
/T (RadioGroup)
/V (Choice1) #<=== correct / expected
>>
print(doc.xref_object(112)) #<=== look at the other button
<<
/Type /Annot
/Subtype /Widget
/AP <<
/N <<
/Off 154 0 R
/Choice2 155 0 R
>>
>>
/AS /Off #<=== correct / as expected
/BS <<
/S /I
/W 1
>>
/F 4
/MK <<
/BC [ 0 ]
/BG [ 1 ]
>>
/P 69 0 R
/Parent 63 0 R
/Rect [ 42.5456 668.792 60.5456 686.792 ]
>>
So, what is going wrong in the following: … ???
btn2.field_value
'Choice2'
The problem is that all widgets are Python objects in memory. Changes in the underlying PDF are not (and cannot be) updated automatically.
Button btn2 must be reloaded from the PDF before we can see the changes:
btn2 = page.load_widget(btn2.xref) #<=== refresh the widget from the PDF
btn2.field_value
'Off'
Maybe what is missing in PyMuPDF is a more mnemonic way to do this: btn2.refresh_widget() or something like that.