Matplotlib 滚动条
我有一个线条简化的算法,想在图表上加一个滚动条,这样可以增加容差,也就是说让线条变得越来越简单。请问用matplotlib怎么实现这个功能?
简单来说,我希望能点击并拖动一个滑块,看到容差增加对线条的影响。
我还是在这方面很挣扎。我只想要一个滑块,范围从1到10。
是的,演示对我有帮助,但我还是在让一个滑块工作上遇到困难,这就是我目前的进展,
fig = mp.figure()
ax = fig.add_subplot(111)
fig.subplots_adjust(left=0.25, bottom=0.25)
min0=1
max0=10
tolerance = 0
chain1 = ChainLoader('Wiggle1.txt')
chain = chain1[0]
chain2 = chain.generalise(tolerance)
axcolor = 'lightgoldenrodyellow'
axmin = fig.add_axes([0.25, 0.1, 0.65, 0.03], axisbg=axcolor)
axmax = fig.add_axes([0.25, 0.15, 0.65, 0.03], axisbg=axcolor)
tolerance = Slider(axmin, 'Min', 1, 10, valinit=min0)
#smax = Slider(axmax, 'Max', 0, 30000, valinit=max0)
def update(val):
tolerance = tolerance.val
#pp.show()
tolerance.on_changed(update)
#smax.on_changed(update)
chain2 = chain.generalise(tolerance)
pp.plotPolylines(chain2)
pp.show()
我遇到的问题是怎么写def update这个部分。谁能帮帮我?
from PointPlotter import PointPlotter
from ChainHandler import ChainLoader
pp=PointPlotter()
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider
ax = plt.subplot(111)
plt.subplots_adjust(left=0.25, bottom=0.25)
tolerance = 0
f0 = 0
chain2 = ChainLoader('Wiggle1.txt')
for chain in chain2:
chain2 = chain.generalise(tolerance)
pp.plotPolylines(chain2)
axcolor = 'lightgoldenrodyellow'
axtol = plt.axes([0.25, 0.1, 0.65, 0.03], axisbg=axcolor)
tolerance = Slider(axtol, 'tol', 0.1, 30.0, valinit=f0)
def update(val):
tolerance = tolerance.val
for chain in chain2:
chain2 = chain.generalise(tolerance)
pp.plotPolylines(chain2)
pp.plotPolylines(chain2)
tolerance.on_changed(update)
plt.show()
快到了!现在可以绘图了,但在使用滚动条时出现了“UnboundLocalError: local variable 'tolerance' referenced before assignment”的错误。@tcaswell 有什么建议吗?
1 个回答
4
你需要使用 slider
小部件,详细信息可以查看这个链接 (文档)。
这里有一个示例演示:
http://matplotlib.org/examples/widgets/slider_demo.html
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider, Button, RadioButtons
ax = plt.subplot(111)
plt.subplots_adjust(left=0.25, bottom=0.25)
t = np.arange(0.0, 1.0, 0.001)
a0 = 5
f0 = 3
s = a0*np.sin(2*np.pi*f0*t)
l, = plt.plot(t,s, lw=2, color='red')
plt.axis([0, 1, -10, 10])
axcolor = 'lightgoldenrodyellow'
axfreq = plt.axes([0.25, 0.1, 0.65, 0.03], facecolor=axcolor)
axamp = plt.axes([0.25, 0.15, 0.65, 0.03], facecolor=axcolor)
sfreq = Slider(axfreq, 'Freq', 0.1, 30.0, valinit=f0)
samp = Slider(axamp, 'Amp', 0.1, 10.0, valinit=a0)
def update(val):
amp = samp.val
freq = sfreq.val
l.set_ydata(amp*np.sin(2*np.pi*freq*t))
plt.draw()
sfreq.on_changed(update)
samp.on_changed(update)
resetax = plt.axes([0.8, 0.025, 0.1, 0.04])
button = Button(resetax, 'Reset', color=axcolor, hovercolor='0.975')
def reset(event):
sfreq.reset()
samp.reset()
button.on_clicked(reset)
rax = plt.axes([0.025, 0.5, 0.15, 0.15], facecolor=axcolor)
radio = RadioButtons(rax, ('red', 'blue', 'green'), active=0)
def colorfunc(label):
l.set_color(label)
plt.draw()
radio.on_clicked(colorfunc)
plt.show()
要把这个适应到你的情况:
#smax.on_changed(update)
chain2 = chain.generalise(tol)
pp.plotPolylines(chain2)
def update(val):
tol = tolerance.val # get the value from the slider
chain2 = chain.generalise(tol) # shove that value into your code
ax.cla() # clear the axes
pp.plotPolylines(chain2) # re-plot your new results
# register the call back
tolerance.on_changed(update)
要小心重复使用变量名(你用 tolerance
两次,一次是浮点数,另一次是 Slider
,Python 会很高兴地用新变量覆盖你之前的变量,类型完全不同)。
在 update
函数中,我采用了最简单粗暴的方法,先清空 axes
,然后重新绘制。一般来说,你应该获取 plotPolylines
返回的对象,并用新的数据更新它们。(如果你在这一步需要帮助,可以另开一个问题,详细说明你的数据结构)。
理解 .on_changed
的方式是,当滑块检测到被改变时,它会调用你传入的函数(update
),并传递一个参数(val
),这个参数是滑块当前的值。在这个函数内部,你可以随意操作,每次滑块改变时,这段代码都会完整执行。