Jupyter Notebook — ipywidgets — автоматическая обратная связь от выбранных
Я пытаюсь создать функцию в блокноте Jupyter, чтобы:
- Дисплей с
ipywidget
серия переключателей из списка опций. - Автоматически отображать выбранное значение.
- Сохраните выбранное значение в переменной.
На данный момент мне удалось выполнить шаг 1 (виджет с именемradio_buttons
в MWE ниже) и создать второйipythonwidget
для отображения результата (виджет с именем, еще не отображающий указанный результат). Я понимаю, что мне нужно привязать выбранный результат к значениюdisplay_result
(попытка с функциейbind_selected_to_output
) но я не понимаю как.
МВЕ
from ipywidgets import interact, widgets
from IPython.display import display
options=["A","B","C"]
# Tentative function to get the input value into the output widget
def bind_selected_to_output(display):
display.value=#The selected value of radio buttons
# The function I am trying to create
def display_radio_buttons(options):
# Input widget
radio_buttons=widgets.RadioButtons(
options=options,
value=None,
disabled=False
# Output widget
display_result=widgets.Text(description = "Saved as:",
disabled=True)
# Trying to monitor selection on the input widget
radio_buttons.observe(bind_selected_to_output(display_result))
# Show the widgets
display(radio_buttons)
display(display_result)
# Return selected value for use elsewhere
return display_result.value
# Use function
display_radio_buttons(options)
)
Как заставить эту функцию работать?
2 ответа
Чтобы дать вам представление о том, как достичь этих трех целей, я пошел и адаптировал свой код, который достигал этих целей в другом контексте с другим виджетом. Я публикую полученный код здесь.
По сути, для первого блока кода мне просто нужно было заменитьToggleButtons
сRadioButtons
чтобы создать блок кода ниже, который бы установил некоторые интерактивные переключатели:
#based on https://stackoverflow.com/a/73832884/8508004 and https://stackoverflow.com/q/65137656/8508004 and https://ipywidgets.readthedocs.io/en/stable/examples/Using%20Interact.html?highlight=interactive#interactive
from ipywidgets import interactive, RadioButtons
def print_choices(choice1, choice2, choice3):
print(choice1)
print(choice2)
print(choice3)
choice1Select = RadioButtons(options=['Not Included', 'Included', 'Favorite'],description='Choice1:',disabled=False,style= {'description_width': '300px'})
choice2Select = RadioButtons(options=['Not Included', 'Included', 'Favorite'],description='Choice2:',disabled=False,style= {'description_width': '300px'})
choice3Select = RadioButtons(options=['Not Included', 'Included', 'Favorite'],description='Choice3:',disabled=False,style= {'description_width': '300px'})
w = interactive(print_choices, choice1=choice1Select, choice2=choice2Select, choice3=choice3Select)
w
Теперь в другой ячейке, чтобы продемонстрировать присвоение значения чему-либо, вам, похоже, не нужно что-то столь же сложное, как то, что у меня было для «примера, встроенного в функцию-оболочку», и поэтому, возможно, этого достаточно в качестве примера сохранения выбранного значения в переменная?:
def return_choice1(choices):
return choices["choice1"]
current_choice1 = return_choice1(w.kwargs)
print(current_choice1)
Адаптируя это более близко к тому, что вы описываете как отображение «серии переключателей из списка опций»:
В процессе адаптации возможна значительная оптимизация, поскольку вам, похоже, нужен только один радио-виджет. И можно обойтись без печати, связанной с исходной функцией, привязанной к интерактивному виджету. Мы даже можем использоватьresult
атрибут виджета, чтобы получить текущее значение. См. документацию для . Объединив все это, вы можете получить следующее для ячейки, которая настраивает виджет и его монитор:
#based on https://stackoverflow.com/a/73832884/8508004 and https://stackoverflow.com/q/65137656/8508004 and https://ipywidgets.readthedocs.io/en/stable/examples/Using%20Interact.html?highlight=interactive#interactive
from ipywidgets import interactive, RadioButtons
options=["A","B","C"]
def radio_selector_monitor(radio_choice_selection):
return radio_choice_selection
radio_selector_widget = RadioButtons(options=options,description='Radio Selector:',disabled=False,style= {'description_width': '300px'})
radio_widget_instance = interactive(radio_selector_monitor, radio_choice_selection=radio_selector_widget)
radio_widget_instance
Теперь в другой ячейке вы можете получить доступ к текущему «результату», выбранному среди вариантов выбора, следующим образом:
print(radio_widget_instance.result)
Это будет соответствовать текущим настройкам. Вы указываете, что ваша третья цель — «Сохранить выбранное значение в переменной».
Сinteractive
use на самом деле нет необходимости «сохранять выбранное значение в переменной», но вы можете это сделать, если вам нужен обработчик с лучшим именем.
Если вы предпочитаете присвоить текущее значение виджета более простой именованной переменной, вы тоже можете это сделать. Однако на самом деле это просто имена одного и того же объекта. Например, если вы набросаете этот код в следующей ячейке, вы можете сделать это:
print(radio_widget_instance.result)
current_radio_choice = radio_widget_instance.result
current_radio_choice
print(current_radio_choice)
print(current_radio_choice is radio_widget_instance.result)
print(current_radio_choice == radio_widget_instance.result)
Другими словами, сейчасradio_widget_instance.result
и указывают на один и тот же объект.
Адаптация упрощенной версии для отображения значения во втором виджете
ОП также указал, что хочет, чтобы значение настройки радио-виджета отображалось как значение второго виджета. Чтобы продемонстрировать это, его блок кода адаптирует код из приведенного выше раздела, чтобы добавить настройку значения второго виджета при обновлении переключателя:
#based on https://stackoverflow.com/a/73832884/8508004 and https://stackoverflow.com/q/65137656/8508004 and https://ipywidgets.readthedocs.io/en/stable/examples/Using%20Interact.html?highlight=interactive#interactive
from ipywidgets import interactive, RadioButtons, Text, VBox
options=["A","B","C"]
output_text = Text()
def radio_selector_monitor_and_binder_to_other_widget(radio_choice_selection):
global current_radio_choice # didn't need as global if just using in this cell, in this function. But if need for later in other cells, make global
current_radio_choice = radio_choice_selection
#display(current_radio_choice) # uncomment this line out if you also the current selection displayed for more feedback
output_text.value = current_radio_choice
return radio_choice_selection
radio_selector_widget = RadioButtons(options=options,description='Radio Selector:',disabled=False,style= {'description_width': '300px'})
radio_widget_instance = interactive(radio_selector_monitor_and_binder_to_other_widget, radio_choice_selection=radio_selector_widget)
VBox([radio_widget_instance, output_text])
Переменную также можно использовать в последующих ячейках для сообщения текущего значения радиоселектора. Еслиcurrent_radio_choice
не должен использоваться за пределами этой ячейки и вне интерактивной функции, то он не обязательно должен быть глобальным.
Asyncio может быть подходящим вариантом, если его невозможно использовать.
Как я уже указывал внизу сюда, это решение вопроса « Можно ли получить текущее значение ползунка виджета из функции без использования многопоточности?»может представлять интерес для тех, кто ищет доступ к текущим значениям. В этом примере использование asyncio позволяет получать обновленную информацию от виджета, который выбирает значение, позволяя при этом использоватьtime.sleep()
который, кажется, блокируетinteractive()
от работы
Я нашел гораздо более практичное решение моей проблемы. Он создает функциюdisplay_radio_buttons
который генерирует переключатели из параметраoptions
(список вариантов для отображения). Выбранный вариант отображается в видеText()
виджет, значение которого связано со значением переключателей. Выбранный вариант также возвращается для последующего использования (например, для печати).
Эту функцию можно легко использовать повторно, поскольку все элементы определены внутри функции.
from ipywidgets import widgets, link
from IPython.display import display
options=["A","B","C"]
def display_radio_buttons(options):
button = widgets.RadioButtons(options=options,description='Radio Selector:')
out = widgets.Text(disabled=True)
l = link((button, 'value'), (out, 'value'))
display(button,out)
return out.value
selected = display_radio_buttons(options)
print(selected)
РЕДАКТИРОВАТЬ после комментария Уэйна
Вместо возврата значенияout
который больше не обновляется,button
возвращается, и его значение позже печатается (или используется), оставаясь обновленным.
from ipywidgets import widgets, link
from IPython.display import display
options=["A","B","C"]
def display_radio_buttons(options):
button = widgets.RadioButtons(options=options,description='Radio Selector:')
out = widgets.Text(disabled=True)
l = link((button, 'value'), (out, 'value'))
display(button, out)
return button
selected = display_radio_buttons(options)
print(selected.value)