matplotlib - 动态地向图形添加滑块
matplotlib - Add sliders to a figure dynamically
基于 this and that 示例,我正在尝试将滑块动态添加到图形(根据绘制的对象的功能)。
滑块是在 for 循环中创建和添加的,每次都会创建一个新的 update()
函数。
问题:滑块不响应任何鼠标输入!
知道如何解决这个问题吗?
import numpy as np
from matplotlib import pyplot as plt
from matplotlib.widgets import Slider
class Plotter:
def __init__(self):
self.fig, self.ax = plt.subplots()
def plot(self, obj):
self.obj = obj
self.l = plt.plot(obj.t,obj.series())
vars = obj.get_variables()
plt.subplots_adjust(bottom=0.03*(len(vars)+2))
for i,var in enumerate(vars):
self.add_slider(i*0.03, var[0], var[1], var[2])
plt.show()
def add_slider(self, pos, name, min, max):
ax = plt.axes([0.1, 0.02+pos, 0.8, 0.02], axisbg='lightgoldenrodyellow')
slider = Slider(ax, name, min, max, valinit=getattr(self.obj, name))
def update(val):
setattr(self.obj, name, val)
self.l.set_ydata(self.obj.series())
self.fig.canvas.draw_idle()
slider.on_changed(update)
class SinFunction:
def __init__(self):
self.freq = 1.0
self.amp = 0.5
self.t = np.arange(0.0, 1.0, 0.001)
def series(self):
return self.amp*np.sin(2*np.pi*self.freq*self.t)
def get_variables(self):
return [
('freq', 0.1, 10),
('amp', 0.1, 1)
]
Plotter().plot(SinFunction())
在 Plotter
class 的 plot
方法中,您将以这种方式获得情节的所有 系列 self.l = plt.plot(obj.t,obj.series())
所以在 self.l
中你有一个对象列表而不是对象本身。你可以有不止一行。
在 add_slider
方法中,您应该将 self.l.set_ydata(self.obj.series())
行更改为 self.l[0].set_ydata(self.obj.series())
以使用对象的方法。在这种情况下,self.l
中只有一个对象,但您可以拥有更多。请考虑到这一点。
此外,要使滑块相应地工作(请参阅下面的评论),它们似乎需要在同一范围内。要在同一范围内设置滑块,您可以创建 sliders attribute
最终代码应该是:
import numpy as np
from matplotlib import pyplot as plt
from matplotlib.widgets import Slider
class Plotter:
def __init__(self):
self.fig, self.ax = plt.subplots()
def plot(self, obj):
self.obj = obj
self.l = plt.plot(obj.t,obj.series())
_vars = obj.get_variables()
plt.subplots_adjust(bottom=0.03*(len(_vars)+2))
self.sliders = []
for i,var in enumerate(_vars):
self.add_slider(i*0.03, var[0], var[1], var[2])
plt.show()
def add_slider(self, pos, name, min, max):
ax = plt.axes([0.1, 0.02+pos, 0.8, 0.02], axisbg='lightgoldenrodyellow')
slider = Slider(ax, name, min, max, valinit=getattr(self.obj, name))
self.sliders.append(slider)
def update(val):
setattr(self.obj, name, val)
self.l[0].set_ydata(self.obj.series())
self.fig.canvas.draw_idle()
slider.on_changed(update)
class SinFunction:
def __init__(self):
self.freq = 1.0
self.amp = 0.5
self.t = np.arange(0.0, 1.0, 0.001)
def series(self):
return self.amp*np.sin(2*np.pi*self.freq*self.t)
def get_variables(self):
return [
('freq', 0.1, 10),
('amp', 0.1, 1)
]
k = Plotter()
k.plot(SinFunction())
此版本适用于 Python 2 和 Python 3。
P.D.: 与 Python 3 相比,我在 Python 2 上看到了不同的行为。我不知道它是否与 Python 或使用 Matplotlib... ¿?
基于 this and that 示例,我正在尝试将滑块动态添加到图形(根据绘制的对象的功能)。
滑块是在 for 循环中创建和添加的,每次都会创建一个新的 update()
函数。
问题:滑块不响应任何鼠标输入!
知道如何解决这个问题吗?
import numpy as np
from matplotlib import pyplot as plt
from matplotlib.widgets import Slider
class Plotter:
def __init__(self):
self.fig, self.ax = plt.subplots()
def plot(self, obj):
self.obj = obj
self.l = plt.plot(obj.t,obj.series())
vars = obj.get_variables()
plt.subplots_adjust(bottom=0.03*(len(vars)+2))
for i,var in enumerate(vars):
self.add_slider(i*0.03, var[0], var[1], var[2])
plt.show()
def add_slider(self, pos, name, min, max):
ax = plt.axes([0.1, 0.02+pos, 0.8, 0.02], axisbg='lightgoldenrodyellow')
slider = Slider(ax, name, min, max, valinit=getattr(self.obj, name))
def update(val):
setattr(self.obj, name, val)
self.l.set_ydata(self.obj.series())
self.fig.canvas.draw_idle()
slider.on_changed(update)
class SinFunction:
def __init__(self):
self.freq = 1.0
self.amp = 0.5
self.t = np.arange(0.0, 1.0, 0.001)
def series(self):
return self.amp*np.sin(2*np.pi*self.freq*self.t)
def get_variables(self):
return [
('freq', 0.1, 10),
('amp', 0.1, 1)
]
Plotter().plot(SinFunction())
在 Plotter
class 的 plot
方法中,您将以这种方式获得情节的所有 系列 self.l = plt.plot(obj.t,obj.series())
所以在 self.l
中你有一个对象列表而不是对象本身。你可以有不止一行。
在 add_slider
方法中,您应该将 self.l.set_ydata(self.obj.series())
行更改为 self.l[0].set_ydata(self.obj.series())
以使用对象的方法。在这种情况下,self.l
中只有一个对象,但您可以拥有更多。请考虑到这一点。
此外,要使滑块相应地工作(请参阅下面的评论),它们似乎需要在同一范围内。要在同一范围内设置滑块,您可以创建 sliders attribute
最终代码应该是:
import numpy as np
from matplotlib import pyplot as plt
from matplotlib.widgets import Slider
class Plotter:
def __init__(self):
self.fig, self.ax = plt.subplots()
def plot(self, obj):
self.obj = obj
self.l = plt.plot(obj.t,obj.series())
_vars = obj.get_variables()
plt.subplots_adjust(bottom=0.03*(len(_vars)+2))
self.sliders = []
for i,var in enumerate(_vars):
self.add_slider(i*0.03, var[0], var[1], var[2])
plt.show()
def add_slider(self, pos, name, min, max):
ax = plt.axes([0.1, 0.02+pos, 0.8, 0.02], axisbg='lightgoldenrodyellow')
slider = Slider(ax, name, min, max, valinit=getattr(self.obj, name))
self.sliders.append(slider)
def update(val):
setattr(self.obj, name, val)
self.l[0].set_ydata(self.obj.series())
self.fig.canvas.draw_idle()
slider.on_changed(update)
class SinFunction:
def __init__(self):
self.freq = 1.0
self.amp = 0.5
self.t = np.arange(0.0, 1.0, 0.001)
def series(self):
return self.amp*np.sin(2*np.pi*self.freq*self.t)
def get_variables(self):
return [
('freq', 0.1, 10),
('amp', 0.1, 1)
]
k = Plotter()
k.plot(SinFunction())
此版本适用于 Python 2 和 Python 3。
P.D.: 与 Python 3 相比,我在 Python 2 上看到了不同的行为。我不知道它是否与 Python 或使用 Matplotlib... ¿?