9

I have some code in a cell in Jupyter notebook using both a radio button and a slider. I have a method which I want called only when the selection is changed (in the case of the radio button); and only when the slider is released (in the case of the slider).

However, using the 'observe' method is triggering multiple times when a radio button is only changed once (it fires 3 times I believe). And the slider observe method fires when the mouse-down and mouse-up occurs.

Can this be changed so that it only is called once or do I need to use something other than observe?

[EDIT] Here is updated example using a radio button along with the output printed when an option is selected once:

import ipywidgets as widgets

    def radio_called(sender):
        print('radio_called')
        print(sender)

    radio = widgets.RadioButtons(options=['option 1', 'option2', 'option3'])
    radio.observe(radio_called)
    display(radio)

Printed output when an option is clicked once: radio_called

{'name': '_property_lock', 'old': traitlets.Undefined, 'new': {'index': 1}, 'owner': RadioButtons(options=('option 1', 'option2', 'option3'), value='option 1'), 'type': 'change'}
radio_called
{'name': 'label', 'old': 'option 1', 'new': 'option2', 'owner': RadioButtons(index=1, options=('option 1', 'option2', 'option3'), value='option 1'), 'type': 'change'}
radio_called
{'name': 'value', 'old': 'option 1', 'new': 'option2', 'owner': RadioButtons(index=1, options=('option 1', 'option2', 'option3'), value='option2'), 'type': 'change'}
radio_called
{'name': 'index', 'old': 0, 'new': 1, 'owner': RadioButtons(index=1, options=('option 1', 'option2', 'option3'), value='option2'), 'type': 'change'}
radio_called
{'name': '_property_lock', 'old': {'index': 1}, 'new': {}, 'owner': RadioButtons(index=1, options=('option 1', 'option2', 'option3'), value='option2'), 'type': 'change'}
laurie
  • 965
  • 1
  • 11
  • 21
  • 1) You have a text field and radio buttons, there is no slider here. 2) What are you trying to do and what is your question/issue ? – Benoit Drogou Aug 26 '19 at 21:52

2 Answers2

11

If you print the sender object you can see what is being passed to the function. Each instance is a different Trait changing (there is more than just a single action happening when you click), try the code below.

If you want to filter to only happen once, in your observe call specify the names you want. E.g.

radio_input.observe(bind_selected_to_output, names=['value'])

    import ipywidgets as widgets # If not already imported

    output_radio_selected = widgets.Text() # Used to take the user input and access it when needed
    radio_input = widgets.RadioButtons(options=['Option 1', 'Option 2']) # Declare the set of radio buttons and provide options

    def bind_selected_to_output(sender): # Connect the input from the user to the output so we can access it
        print(sender)
        global selected_option # Global variable to hold the user input for reuse in your code
        output_radio_selected.value = radio_input.value
        selected_option = output_radio_selected.value # Example variable assigned the selected value
        print('Selected option set to: ' + selected_option) # For test purposes

    radio_input.observe(bind_selected_to_output, names=['value']) # Run the bind... function when the radio button is changed
    radio_input # Display the radio buttons to the user

See here for more info: https://ipywidgets.readthedocs.io/en/latest/examples/Widget%20Events.html#Traitlet-events

ac24
  • 5,325
  • 1
  • 16
  • 31
  • Thanks - being able to print the sender status is really helpful. I made another simple radio button and printed the sender when I clicked a different option. Have updated post with details. – laurie Aug 30 '19 at 14:47
  • 1
    I also specified how only get one printed, just before the big code block. `radio_input.observe(bind_selected_to_output, names=['value'])` – ac24 Aug 30 '19 at 15:05
  • Yep - thanks I got it running. When I read that I was expecting the 'value' to be a specific string that I needed to take from the sender object, I didn't realize it was a literally the string 'value – laurie Aug 30 '19 at 19:52
  • @ac24 , the code is outdated in regards handling output. It goes to Log console this way now. I'm adding a version that works in JupyterLab so that the output isn't going to the Log console instead. I'm happy to delete my example if you want to update yours. Note that the code can be tested without touching anything on your own system using a remote temporary session to test by using links at the bottom of [here](https://stackoverflow.com/a/75440619/8508004). – Wayne Aug 31 '23 at 19:27
0

Here's an updated version of ac24's code so that the output is handled correctly and doesn't go to the Log console when run in JupyterLab:

import ipywidgets as widgets # If not already imported

OUT = widgets.Output()

output_radio_selected = widgets.Text() # Used to take the user input and access it when needed
radio_input = widgets.RadioButtons(options=['Option 1', 'Option 2']) # Declare the set of radio buttons and provide options

def bind_selected_to_output(sender): # Connect the input from the user to the output so we can access it
    OUT.clear_output()
    with OUT:
        print(sender)
    global selected_option # Global variable to hold the user input for reuse in your code
    output_radio_selected.value = radio_input.value
    selected_option = output_radio_selected.value # Example variable assigned the selected value
    with OUT:
        print('Selected option set to: ' + selected_option) # For test purposes

radio_input.observe(bind_selected_to_output, names=['value']) # Run the bind... function when the radio button is changed
#radio_input # Display the radio buttons to the user
display(radio_input,OUT)
Wayne
  • 6,607
  • 8
  • 36
  • 93