问题
I can register a handler to button.on_click in ipython notebook widgets, but I don't know how to do the same for a dropdown widget
import ipywidgets as widgets
from IPython.display import display
def on_button_clicked(b):
print("Button clicked.")
button = widgets.Button(description="Click Me!")
display(button)
button.on_click(on_button_clicked)
But for
choose_task = widgets.Dropdown(
options=['Addition', 'Multiplication', 'Subtraction'],
value='Addition',
description='Task:',
)
there seems to be only
on_trait_change(...)
if I register a handler with this, can I use it to access the value of the widget? I have seen examples with the handler and the widget belong to a subclass, and the handler can use self to introspect. But if I don't want to use a subclass, how does the handler know what widget was the target of the event.?
回答1:
Between this link and the traitlet docs on github and just playing around, I finally figured this out:
w = widgets.Dropdown(
options=['Addition', 'Multiplication', 'Subtraction'],
value='Addition',
description='Task:',
)
def on_change(change):
if change['type'] == 'change' and change['name'] == 'value':
print "changed to %s" % change['new']
w.observe(on_change)
display(w)
Overall this looks a lot richer than the deprecated interface, but it could definitely use more examples.
回答2:
Put it all together
Inspired on previous answers and lambda expressions I use this:
def function(option):
print(option)
w = widgets.Dropdown(
options=['None', 'Option 1', 'Option 2', 'Option 3'],
description='Option:',
disabled=False
)
w.observe(
lambda c: plot_content(c['new']) if (c['type'] == 'change' and c['name'] == 'value') else None
)
display(w)
回答3:
I agree that event handling is not as thorough as would be desired: I have been filtering the events as you receive multiple events for a typical dropdown change as the index changes, the value changes, i.e., change['name'].
I am doing the following:
def on_dropdown_change(change):
if change['name'] == 'value' and (change['new'] != change['old']):
print('do something with the change')
dropdown = ipywidgets.Dropdown({options=['one','two','three'],
value='one'})
dropdown.observe(on_dropdown_change)
回答4:
You can specify the change name in observe. This makes for cleaner code, and the handler is not called for changes you don't need:
from IPython.display import display
from ipywidgets import Dropdown
def dropdown_eventhandler(change):
print(change.new)
option_list = (1, 2, 3)
dropdown = Dropdown(description="Choose one:", options=option_list)
dropdown.observe(dropdown_eventhandler, names='value')
display(dropdown)
回答5:
I believe the idea is to use trait name, e.g. value. For example:
from ipywidgets import Dropdown
def handle_change():
print type_sel.value
type_sel = Dropdown(description="Keypoint type", options=['surf', 'orb'])
type_sel.on_trait_change(handle_change, name="value")
display(type_sel)
SciPy 2015 Advanced Jupyter Video Tutorial
回答6:
I had the same issue. This also begs the next question, how to interface button actions based on dropdown menu selections.
# Common Imports for Widgets
from __future__ import print_function
from ipywidgets import interact, interactive, fixed, interact_manual
import ipywidgets as widgets
'''
Precusor:
<class 'traitlets.utils.bunch.Bunch'> It is a dictionary-like object containing:
{'name': 'value', 'old': 'what_ever_the_old_value_was', 'new': 'what_ever_the_new_value_is',
'owner': Dropdown(description='the_user_defined_label:', index=1, # I'm not sure what this is
options=()#list of options passed,
value='value_kwarg_value'), 'type': 'change'} # type: action_or_event type
For more information see:
https://traitlets.readthedocs.io/en/stable/using_traitlets.html#default-values-and-checking-type-and-value
or
https://github.com/jupyter-widgets/tutorial/blob/master/notebooks/08.00-Widget_Events.ipynb
or a long but well done SciPy talk on the use of widgets @
https://www.youtube.com/watch?v=HaSpqsKaRbo
'''
foo = ['a','b','c'] # List to use
# Function to apply to drop box object
def bar(x):
'''
I am intentionally passing what it is made of so you can see the output.
'''
print(x,'\n') # Whole object
print(x.new,'\n') # New value
# Function for the button to select user input and do work
def get_user_selection(a): # A default arg is needed here, I am guessing to pass self
# Displays the current value of dropbox1 and dropbox two
display(dropbox1.value,dropbox2.value)
# creation of a widget dropdown object called dropbox1
dropbox1 = widgets.Dropdown(
options=foo, # Object to iterate over
description='Letter:', # User defined
value=foo[1], # Default value selection
rows=len(foo), # The number of rows to display when showing the box
interactive=True, # This makes the box interactive, I believe this is true by default
);
# Drop box of k,v like pairs
dropbox2 = widgets.Dropdown(
options=[('One', 1), ('Two', 2), ('Three', 3)],
value=2,
description='Number:',
)
# Button to click
select_button = widgets.Button(
description='Click', # User defined
disabled=False
)
# Event Handlers
dropbox1.observe(bar,names='value')
dropbox2.observe(bar,names='value')
select_button.on_click(get_user_selection)
# I you need more help with commands try things like:
# interact_manual?
# display(arg.keys,arg.traits)
# print(widgets.widget_type_here.widget_function_or_attr.__doc__)
# Create a UI object to display things. There are other ways of organizing them.
ui = widgets.HBox([dropbox1,dropbox2,select_button]) # pass an array of widgets to the ui
# display the UI
display(ui)
This will display the following after a couple of clicks.
来源:https://stackoverflow.com/questions/34020789/ipywidgets-dropdown-widgets-what-is-the-onchange-event