3 回答
![?](http://img1.sycdn.imooc.com/5458453d0001cd0102200220-100-100.jpg)
TA贡献1772条经验 获得超5个赞
要完成此操作,您必须使用更多手动interactive_output功能。该函数允许您预先创建小部件,然后将它们传入:
import ipywidgets as widgets
import numpy as np
import matplotlib.pyplot as plt
start_slider = widgets.FloatSlider(
val = 0,
min = 0,
max = np.pi*0.9,
step = np.pi*0.1,
description = 'Starts at'
)
end_slider = widgets.FloatSlider(
val = np.pi,
min = np.pi,
max = 2*np.pi,
step = np.pi*0.1,
description = 'Ends at'
)
def on_button_clicked(_):
start_slider.value = 0
end_slider.value = 2*np.pi
button = Button(description="Reset")
button.on_click(on_button_clicked)
def plot_graph(starts_at=0, ends_at=2*np.pi):
f = lambda x : sum(1/a*np.sin(a*x + np.pi/a) for a in range(1,6))
x = np.linspace(0, 2*np.pi, 1000)
plt.plot(x, f(x))
plt.xlim([starts_at, ends_at])
display(widgets.VBox([start_slider, end_slider, button]))
widgets.interactive_output(plot_graph, {'starts_at': start_slider, 'ends_at':end_slider})
然而,这将在您每次更新时完全重新生成情节,这可能会导致不稳定的体验。因此,您还可以重写它以使用 matplotlib 方法,就像.set_data
在笔记本中使用交互式 matplotlib 后端一样。因此,如果您要使用ipympl,您可以按照此示例笔记本中的示例进行操作。
通过另一个图书馆
我编写了一个mpl-interactions库,以便更轻松地使用 ipywidgets 滑块控制 matplotlib 绘图。ipywidgets.interact
它提供了一个类似于为您创建小部件的功能,但它的优点是专注于 matplotlib,因此您需要提供的只是数据。%matplotlib ipympl
import mpl_interactions.ipyplot as iplt
import matplotlib.pyplot as plt
import numpy as np
import ipywidgets as widgets
def plot_graph(starts_at=0, ends_at=2*np.pi):
x = np.linspace(starts_at, ends_at, 1000)
f = lambda x : sum(1/a*np.sin(a*x + np.pi/a) for a in range(1,6))
return np.array([x, f(x)]).T
fig, ax = plt.subplots()
button = widgets.Button(description = 'reset')
display(button)
controls = iplt.plot(plot_graph, starts_at = (0, np.pi), ends_at = (np.pi, 2*np.pi), xlim='auto', parametric=True)
def on_click(event):
for hbox in controls.controls.values():
slider = hbox.children[0]
slider.value = slider.min
button.on_click(on_click)
![?](http://img1.sycdn.imooc.com/545862120001766302200220-100-100.jpg)
TA贡献1802条经验 获得超6个赞
我可以在不使用装饰器的情况下弄清楚它@interact(现在它正在工作),但我对最终结果不满意。所以,我仍然愿意为那些可以做出清晰/更简单的Python版本的人提供正确的答案状态。
无论如何,这是工作代码:
import numpy as np
import matplotlib.pyplot as plt
from ipywidgets import interact, Button, FloatSlider
def plot_graph(starts_at, ends_at):
f = lambda x : sum(1/a*np.sin(a*x + np.pi/a) for a in range(1,6))
x = np.linspace(0, 2*np.pi, 1000)
plt.plot(x, f(x))
plt.xlim([starts_at, ends_at])
starts_at = FloatSlider(min=0, max=np.pi*0.9, value=0, step=np.pi*0.1)
ends_at = FloatSlider(min=np.pi, max=2*np.pi, value=2*np.pi, step=np.pi*0.1)
def on_button_clicked(_):
starts_at.value = 0
ends_at.value = 2*np.pi
button = Button(description="Reset")
button.on_click(on_button_clicked)
display(button)
_ = interact(plot_graph, starts_at=starts_at, ends_at=ends_at)
编辑:从这一点开始的新方法================================
我选择 @Ianhi 答案作为正确的答案,因为他指出了在我的问题背景下要考虑的问题。谢谢!
不管怎样,我在这里发布了我正在使用的最终方案,该方案对于我的需求来说足够简单,并且我可以在所有交互中重复使用重置按钮:
# Preamble ----
import numpy as np
import matplotlib.pyplot as plt
from ipywidgets import interact, Button, FloatSlider
def reset_button(defaults={}):
def on_button_clicked(_):
for k, v in defaults.items():
k.value = v
button = Button(description='Reset')
button.on_click(on_button_clicked)
display(button)
# Code ----
slider1 = FloatSlider(min=0, max=np.pi*0.9, value=0, step=np.pi*0.1)
slider2 = FloatSlider(min=np.pi, max=2*np.pi, value=2*np.pi, step=np.pi*0.1)
reset_button(defaults={slider1: 0, slider2: 2*np.pi})
@interact(starts_at=slider1, ends_at=slider2)
def plot_graph(starts_at, ends_at):
f = lambda x : sum(1/a*np.sin(a*x + np.pi/a) for a in range(1,6))
x = np.linspace(0, 2*np.pi, 1000)
plt.plot(x, f(x))
plt.xlim([starts_at, ends_at])
![?](http://img1.sycdn.imooc.com/5333a1bc00014e8302000200-100-100.jpg)
TA贡献1827条经验 获得超9个赞
您可以创建一个简单的装饰器,为每次使用添加一个重置按钮:
按照上面的答案重置按钮:
def reset_button(defaults={}):
def on_button_clicked(_):
for k, v in defaults.items():
k.value = v
button = widgets.Button(description='Reset')
button.on_click(on_button_clicked)
display(button)
装饰者:
def interact_plus_reset(**_widgets):
default_vals = {wid:wid._trait_values['value'] for k, wid in _widgets.items()}
reset_button(defaults=default_vals)
def wrap(func):
@wraps(func)
@widgets.interact(**_widgets)
def inner(*args, **kwargs):
return func(*args, **kwargs)
return inner
return wrap
然后按如下方式使用它:
@interact_plus_reset(
a = widgets.FloatSlider(min=1, max=2000, value=35, step=1),
b = widgets.FloatSlider(min=1, max=2000, value=1000, step=1),
)
def run(a, b):
print(a + b)
添加回答
举报