peterbrittain / asciimatics

A cross platform package to do curses-like operations, plus higher level APIs and widgets to create text UIs and ASCII art animations
Apache License 2.0
3.61k stars 238 forks source link

RadioButton value equals None when set to False #355

Closed knack-shawn closed 2 years ago

knack-shawn commented 2 years ago

Describe the bug When a RadioButton options value should be set to False, it evaluates to None

To Reproduce mcve.py

#!/usr/bin/env python3

from asciimatics.widgets import Frame, Layout, RadioButtons, Button
from asciimatics.scene import Scene
from asciimatics.screen import Screen
from asciimatics.exceptions import ResizeScreenError, StopApplication
import sys, time

class Simple(Frame):
    def __init__(self, screen):
        super().__init__(screen, screen.height,
                         screen.width)
        self.layout = Layout([1], fill_frame=True)
        self.add_layout(self.layout)
        self.rb = RadioButtons(label=('example_button'), options=[ (("True"),True) , (('False'),False)])
        self.layout.add_widget(self.rb)
        check_value = Button('check_value', self._store_val)
        self.layout.add_widget(check_value)
        self.fix()

    def _store_val(self):
        value = self.rb._value
        time.sleep(1)

def demo(screen, scene):
    scenes = [
        Scene([Simple(screen)], -1, name="example")
    ]

    screen.play(scenes, stop_on_resize=True, start_scene=scene, allow_int=True)

last_scene = None
while True:
    try:
        Screen.wrapper(demo, catch_interrupt=True, arguments=[last_scene])
        sys.exit(0)
    except ResizeScreenError as e:
        last_scene = e.scene

Expected behavior I would expect rb.value = False. I would like to be able to get a boolean

System details (please complete the following information):

Additional context quick fix in widgets/radiobuttons.py line 115


#This will not allow a radio button to be set to False
self._value = new_value if new_value else None

=>

self._value = new_value

peterbrittain commented 2 years ago

Strictly speaking, your mcve is accessing a private field. Your application should be using self.rb.value (note the lack of underscore). If you make that change, the code works as expected. That said, I'm not entirely happy with this code, so I'll tweak it to be more consistent in its internal state.