Add a vertical slider with matplotlib

匿名 (未验证) 提交于 2019-12-03 03:06:01

问题:

I would like to create a vertical slider widget instead horizontal slider with matplotlib.

I have found a good example in the matplotlib webpage http://matplotlib.org/examples/widgets/slider_demo.html but I do not know how to move the slider in the Y axis and change the slider labels. I can change the position of the axis but not the movement of the slider. The example is here:

import numpy as np import matplotlib.pyplot as plt from matplotlib.widgets import Slider, Button, RadioButtons  fig, ax = plt.subplots() 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.03, 0.25, 0.03, 0.65], axisbg=axcolor) axamp = plt.axes([0.08, 0.25, 0.03, 0.65], axisbg=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))     fig.canvas.draw_idle() 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.5, 0.025, 0.15, 0.15], axisbg=axcolor) radio = RadioButtons(rax, ('red', 'blue', 'green'), active=0) def colorfunc(label):     l.set_color(label)     fig.canvas.draw_idle() radio.on_clicked(colorfunc)  plt.show() 

回答1:

This is not possible out of the box, because the matplotlib.widgets.Slider implementation uses axvspan and axvline to define the slider bar (which is a patches.Polygon), and updates it according to the horizontal assumption. It is not too difficult to write your own vertical slider using the horizontal slider as an example (you would likewise subclass from AxesWidget), but it has to be done yourself.

Valid as of matplotlib 2.0: A vertical slider class is given below; it works just like the horizontal one, except it is ... well ... vertical!

from matplotlib.widgets import AxesWidget import six  class VertSlider(AxesWidget):     """     A slider representing a floating point range.      For the slider to remain responsive you must maintain a     reference to it.      The following attributes are defined       *ax*        : the slider :class:`matplotlib.axes.Axes` instance        *val*       : the current slider value        *hline*     : a :class:`matplotlib.lines.Line2D` instance                      representing the initial value of the slider        *poly*      : A :class:`matplotlib.patches.Polygon` instance                      which is the slider knob        *valfmt*    : the format string for formatting the slider text        *label*     : a :class:`matplotlib.text.Text` instance                      for the slider label        *closedmin* : whether the slider is closed on the minimum        *closedmax* : whether the slider is closed on the maximum        *slidermin* : another slider - if not *None*, this slider must be                      greater than *slidermin*        *slidermax* : another slider - if not *None*, this slider must be                      less than *slidermax*        *dragging*  : allow for mouse dragging on slider      Call :meth:`on_changed` to connect to the slider event     """     def __init__(self, ax, label, valmin, valmax, valinit=0.5, valfmt='%1.2f',                  closedmin=True, closedmax=True, slidermin=None,                  slidermax=None, dragging=True, **kwargs):         """         Create a slider from *valmin* to *valmax* in axes *ax*.          Additional kwargs are passed on to ``self.poly`` which is the         :class:`matplotlib.patches.Rectangle` which draws the slider         knob.  See the :class:`matplotlib.patches.Rectangle` documentation         valid property names (e.g., *facecolor*, *edgecolor*, *alpha*, ...).          Parameters         ----------         ax : Axes             The Axes to put the slider in          label : str             Slider label          valmin : float             The minimum value of the slider          valmax : float             The maximum value of the slider          valinit : float             The slider initial position          label : str             The slider label          valfmt : str             Used to format the slider value, fprint format string          closedmin : bool             Indicate whether the slider interval is closed on the bottom          closedmax : bool             Indicate whether the slider interval is closed on the top          slidermin : Slider or None             Do not allow the current slider to have a value less than             `slidermin`          slidermax : Slider or None             Do not allow the current slider to have a value greater than             `slidermax`           dragging : bool             if the slider can be dragged by the mouse          """         AxesWidget.__init__(self, ax)          self.valmin = valmin         self.valmax = valmax         self.val = valinit         self.valinit = valinit         self.poly = ax.axhspan(valmin, valinit, 0, 1, **kwargs)          self.hline = ax.axhline(valinit, 0, 1, color='r', lw=1)          self.valfmt = valfmt         ax.set_xticks([])         ax.set_ylim((valmin, valmax))         ax.set_yticks([])         ax.set_navigate(False)          self.connect_event('button_press_event', self._update)         self.connect_event('button_release_event', self._update)         if dragging:             self.connect_event('motion_notify_event', self._update)         self.label = ax.text(0.5, 1.03, label, transform=ax.transAxes,                              verticalalignment='center',                              horizontalalignment='center')          self.valtext = ax.text(0.5, -0.03, valfmt % valinit,                                transform=ax.transAxes,                                verticalalignment='center',                                horizontalalignment='center')          self.cnt = 0         self.observers = {}          self.closedmin = closedmin         self.closedmax = closedmax         self.slidermin = slidermin         self.slidermax = slidermax         self.drag_active = False      def _update(self, event):         """update the slider position"""         if self.ignore(event):             return          if event.button != 1:             return          if event.name == 'button_press_event' and event.inaxes == self.ax:             self.drag_active = True             event.canvas.grab_mouse(self.ax)          if not self.drag_active:             return          elif ((event.name == 'button_release_event') or               (event.name == 'button_press_event' and                event.inaxes != self.ax)):             self.drag_active = False             event.canvas.release_mouse(self.ax)             return          val = event.ydata         if val <= self.valmin:             if not self.closedmin:                 return             val = self.valmin         elif val >= self.valmax:             if not self.closedmax:                 return             val = self.valmax          if self.slidermin is not None and val <= self.slidermin.val:             if not self.closedmin:                 return             val = self.slidermin.val          if self.slidermax is not None and val >= self.slidermax.val:             if not self.closedmax:                 return             val = self.slidermax.val          self.set_val(val)      def set_val(self, val):         xy = self.poly.xy         xy[1] = 0, val         xy[2] = 1, val         self.poly.xy = xy         self.valtext.set_text(self.valfmt % val)         if self.drawon:             self.ax.figure.canvas.draw_idle()         self.val = val         if not self.eventson:             return         for cid, func in six.iteritems(self.observers):             func(val)      def on_changed(self, func):         """         When the slider value is changed, call *func* with the new         slider position          A connection id is returned which can be used to disconnect         """         cid = self.cnt         self.observers[cid] = func         self.cnt += 1         return cid      def disconnect(self, cid):         """remove the observer with connection id *cid*"""         try:             del self.observers[cid]         except KeyError:             pass      def reset(self):         """reset the slider to the initial value if needed"""         if (self.val != self.valinit):             self.set_val(self.valinit) 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!