我正在使用 matplotlib 滑块,类似于此演示。目前滑块使用 2 位小数并且“感觉”非常连续(尽管它们在某种程度上必须是离散的)。我能决定它们以哪种级别离散吗?整数步长?0.1 大小的步长?0.5?我的谷歌搜索无果。
我正在使用 matplotlib 滑块,类似于此演示。目前滑块使用 2 位小数并且“感觉”非常连续(尽管它们在某种程度上必须是离散的)。我能决定它们以哪种级别离散吗?整数步长?0.1 大小的步长?0.5?我的谷歌搜索无果。
如果你只需要整数值,创建滑块时只需传入适当的valfmt
(例如,valfmt ='%0.0f'
)即可。
但是,如果你想要非整数间隔,你需要每次手动设置文本值。即使你这样做了,滑块仍然会平稳地进展,而不会“感觉”像离散间隔。
以下是一个例子:
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.widgets import Slider
class ChangingPlot(object):
def __init__(self):
self.inc = 0.5
self.fig, self.ax = plt.subplots()
self.sliderax = self.fig.add_axes([0.2, 0.02, 0.6, 0.03],
axisbg='yellow')
self.slider = Slider(self.sliderax, 'Value', 0, 10, valinit=self.inc)
self.slider.on_changed(self.update)
self.slider.drawon = False
x = np.arange(0, 10.5, self.inc)
self.ax.plot(x, x, 'ro')
self.dot, = self.ax.plot(self.inc, self.inc, 'bo', markersize=18)
def update(self, value):
value = int(value / self.inc) * self.inc
self.dot.set_data([[value],[value]])
self.slider.valtext.set_text('{}'.format(value))
self.fig.canvas.draw()
def show(self):
plt.show()
p = ChangingPlot()
p.show()
matplotlib.widgets.Slider
的子类。关键效果由Slider.set_val
控制。class DiscreteSlider(Slider):
"""A matplotlib slider widget with discrete steps."""
def __init__(self, *args, **kwargs):
"""Identical to Slider.__init__, except for the "increment" kwarg.
"increment" specifies the step size that the slider will be discritized
to."""
self.inc = kwargs.pop('increment', 0.5)
Slider.__init__(self, *args, **kwargs)
def set_val(self, val):
discrete_val = int(val / self.inc) * self.inc
# We can't just call Slider.set_val(self, discrete_val), because this
# will prevent the slider from updating properly (it will get stuck at
# the first step and not "slide"). Instead, we'll keep track of the
# the continuous value as self.val and pass in the discrete value to
# everything else.
xy = self.poly.xy
xy[2] = discrete_val, 1
xy[3] = discrete_val, 0
self.poly.xy = xy
self.valtext.set_text(self.valfmt % discrete_val)
if self.drawon:
self.ax.figure.canvas.draw()
self.val = val
if not self.eventson:
return
for cid, func in self.observers.iteritems():
func(discrete_val)
以下是使用它的完整示例:
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.widgets import Slider
class ChangingPlot(object):
def __init__(self):
self.inc = 0.5
self.fig, self.ax = plt.subplots()
self.sliderax = self.fig.add_axes([0.2, 0.02, 0.6, 0.03],
facecolor='yellow')
self.slider = DiscreteSlider(self.sliderax, 'Value', 0, 10,
increment=self.inc, valinit=self.inc)
self.slider.on_changed(self.update)
x = np.arange(0, 10.5, self.inc)
self.ax.plot(x, x, 'ro')
self.dot, = self.ax.plot(self.inc, self.inc, 'bo', markersize=18)
def update(self, value):
self.dot.set_data([[value],[value]])
self.fig.canvas.draw()
def show(self):
plt.show()
class DiscreteSlider(Slider):
"""A matplotlib slider widget with discrete steps."""
def __init__(self, *args, **kwargs):
"""Identical to Slider.__init__, except for the "increment" kwarg.
"increment" specifies the step size that the slider will be discritized
to."""
self.inc = kwargs.pop('increment', 0.5)
Slider.__init__(self, *args, **kwargs)
self.val = 1
def set_val(self, val):
discrete_val = int(val / self.inc) * self.inc
# We can't just call Slider.set_val(self, discrete_val), because this
# will prevent the slider from updating properly (it will get stuck at
# the first step and not "slide"). Instead, we'll keep track of the
# the continuous value as self.val and pass in the discrete value to
# everything else.
xy = self.poly.xy
xy[2] = discrete_val, 1
xy[3] = discrete_val, 0
self.poly.xy = xy
self.valtext.set_text(self.valfmt % discrete_val)
if self.drawon:
self.ax.figure.canvas.draw()
self.val = val
if not self.eventson:
return
for cid, func in self.observers.items():
func(discrete_val)
p = ChangingPlot()
p.show()
如果您不想子类化滑块,则可以使用@Joe Kington的答案中的几行代码来在回调函数中完成离散化:
sldr = Slider(ax,'name',0.,5.,valinit=0.,valfmt="%i")
sldr.on_changed(partial(set_slider,sldr))
然后:
def set_slider(s,val):
s.val = round(val)
s.poly.xy[2] = s.val,1
s.poly.xy[3] = s.val,0
s.valtext.set_text(s.valfmt % s.val)