我可以使matplotlib滑块更离散吗? [英] Can I make matplotlib sliders more discrete?

查看:96
本文介绍了我可以使matplotlib滑块更离散吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用matplotlib滑块,类似于此演示.滑块当前使用2个小数位,并且感觉"相当连续(尽管它们必须在某种程度上是离散的).我可以决定它们在什么级别上是离散的吗?整数步? 0.1步大小? 0.5?我的Google Fu使我失败了.

I'm using matplotlib sliders, similar to this demo. The sliders currently use 2 decimal places and 'feel' quite continuous (though they have to be discrete on some level). Can I decide on what level they are discrete? Integer steps? 0.1-sized steps? 0.5? My google-fu failed me.

推荐答案

如果只需要整数值,则在创建滑块时(例如valfmt='%0.0f')只需传入一个合适的valfmt

If you just want integer values, just pass in an approriate valfmt when you create the slider (e.g. valfmt='%0.0f')

但是,如果要使用非整数的inverval,则每次都需要手动设置文本值.即使执行此操作,滑块仍将平稳前进,并且不会像离散时间间隔一样感觉".

However, if you want non-integer invervals, you'll need to manually set the text value each time. Even if you do this, though, the slider will still progress smoothly, and it won't "feel" like discrete intervals.

这是一个例子:

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

If you wanted to make the slider "feel" completely like discrete values, you could subclass matplotlib.widgets.Slider. The key effect is controlled by Slider.set_val

在这种情况下,您将执行以下操作:

In that case, you'd do something like this:

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)

并作为使用它的完整示例:

And as a full example of using it:

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()

这篇关于我可以使matplotlib滑块更离散吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆