Matplotlib 滚动条

1 投票
1 回答
20525 浏览
提问于 2025-04-17 14:34

我有一个线条简化的算法,想在图表上加一个滚动条,这样可以增加容差,也就是说让线条变得越来越简单。请问用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),这个参数是滑块当前的值。在这个函数内部,你可以随意操作,每次滑块改变时,这段代码都会完整执行。

撰写回答