【问题标题】:Discrete slider in matplotlib widgetmatplotlib 小部件中的离散滑块
【发布时间】:2014-05-17 09:24:18
【问题描述】:

基于this solution,我想制作一个只允许指定值的滑块,滑块本身也是离散的,滑块只有在选择新点时才会移动(所以基本上是单选按钮的滑块版本) .例如,如果我在当前点附近但不完全单击,则滑块不应更改并且绘图不应重绘。

我得到了它几乎工作,但结果滞后:如果我在下面的示例中交替单击 1 和 10,滑块会正确更新,但移动点总是跳到前一个值。我该如何解决它:

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.widgets import Slider

class ChangingPlot(object):
    def __init__(self):
        self.draw_counter = 0
        x = np.logspace(0, 1, 10)

        self.fig, self.ax = plt.subplots()
        self.sliderax     = self.fig.add_axes([0.2, 0.02, 0.6, 0.03],axisbg='yellow')
        self.slider       = DiscreteSlider(self.sliderax,'Value', 0, 10,\
                                           allowed_vals=x, valinit=x[0])

        self.slider.on_changed(self.update)

        self.ax.plot(x, x, 'ro')
        self.dot, = self.ax.plot(x[0], x[0], 'bo', markersize=18)
        self.text = self.ax.text(2,8,str(self.draw_counter))

    def update(self, value):
        self.draw_counter += 1
        self.dot.set_data([[value],[value]])
        self.text.set_text(str(self.draw_counter)+' draws, value = '+str(value))

    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 new keyword 'allowed_vals'.
        This keyword specifies the allowed positions of the slider
        """
        self.allowed_vals = kwargs.pop('allowed_vals',None)
        self.previous_val = kwargs['valinit']
        Slider.__init__(self, *args, **kwargs)
        if self.allowed_vals==None:
            self.allowed_vals = [self.valmin,self.valmax]

    def set_val(self, val):
        discrete_val = self.allowed_vals[abs(val-self.allowed_vals).argmin()]
        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 self.previous_val!=discrete_val:
            self.previous_val = discrete_val
            if not self.eventson: 
                return
            for cid, func in self.observers.iteritems():
                func(discrete_val)

p = ChangingPlot()
p.show()

【问题讨论】:

  • 感谢分享。我只需要在函数set_val 中将行self.val = val 更改为self.val = discrete_val
  • @JohnSmith 这太棒了!也正是我(可能还有其他人)需要的。您应该应用 HYRY 建议的修复并将其作为拉取请求提交到 matplotlib github 存储库。

标签: python matplotlib widget


【解决方案1】:

很好的例子,你需要调用Figure.canvas.draw()来刷新屏幕:

def update(self, value):
    self.draw_counter += 1
    self.dot.set_data([[value],[value]])
    self.text.set_text(str(self.draw_counter)+' draws, value = '+str(value))
    self.fig.canvas.draw() # <--- Add this line

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-09
    • 2023-03-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多