【发布时间】:2019-07-09 21:15:54
【问题描述】:
这是一个高度抽象的主程序和模块。 Matplotlib 滑块小部件应导致 Data 实例重新计算,然后绘图应更新。
每次更新滑块时,它都应将其新值传递给在滑块实例化期间定义的适当方法。例如,移动第一个滑块应将其值发送到d1.set_a(),这会触发对该数据的重新计算,然后应触发P.offsets()(请参阅模块)以更新绘图。
问题:我怎样才能让这些用户定义的、脚本生成的滑块来触发数据对象和图的更新? Slider Widgets 实例是否提供比我在这里做的方式更方便的方法?
主程序:
import numpy as np
from MODULE import Data, Plot
x0 = np.linspace(0, 10., 11)
y1, y2 = [0.5 * (1.0 + f(x0)) for f in (np.cos, np.sin)]
d1, d2 = Data('hey', x0, y1), Data('wow', x0, y2) # data generating objects
p = Plot('hey') # plot object
p.add_slider(d1, 'set_a', d1.a, (0.2, 1.0))
p.add_slider(d1, 'set_p', d1.p, (0.5, 2.0))
p.add_slider(d2, 'set_a', d2.a, (0.2, 1.0))
p.add_slider(d2, 'set_p', d2.p, (0.5, 2.0))
p.plotme((d1, d2))
当前结果,滑块移动但不触发重新计算/重新绘制:
模块:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider
class Plot(object):
def __init__(self, name):
self.name = name
self.sliders = []
self.axcolor = 'lightgoldenrodyellow'
self.fig = plt.figure()
def sliderfunc(self, value):
print('sliderfunc') # currently not getting here
for (obj, P) in self.OPs:
P.set_offsets(obj.xy.T)
self.fig.canvas.draw_idle()
def add_slider(self, obj, method, nominal, limits):
ybot = 0.03 * (len(self.sliders) + 1)
name = obj.name + '.' + method
ax_slider = plt.axes([0.25, ybot, 0.50, 0.02], facecolor=self.axcolor)
slider = Slider(ax_slider, name, limits[0], limits[1],
valinit=nominal)
slider.on_changed(getattr(obj, method)) # this may not be right
self.sliders.append(slider)
return slider
def plotme(self, objs):
ybot = 0.03 * (len(self.sliders) + 3)
A = plt.axes([0.15, ybot, 0.65, 0.50])
self.OPs = []
for obj in objs:
P = A.scatter(obj.x, obj.y)
self.OPs.append((obj, P))
plt.show()
class Data(object):
def __init__(self, name, x0, y0):
self.name = name
self.a = 1.0
self.p = 1.0
self.x0, self.y0 = x0, y0
self.setstuff(a=1.0, p=1.0)
def setstuff(self, a=None, p=None):
if a != None:
self.set_a(a)
if p != None:
self.set_p(p)
def set_a(self, a):
self.a = a
self.x = self.a * self.x0
self.y = self.y0**self.p
self.xy = np.vstack((self.x, self.y))
def set_p(self, p):
self.p = p
self.x = self.a * self.x0
self.y = self.y0**self.p
self.xy = np.vstack((self.x, self.y))
【问题讨论】:
-
可能您只是忘记将
Slider分配给变量。如果你不这样做,它将被垃圾收集(因为所有没有引用的对象都会在 python 中)并在创建后立即从内存中删除。 -
@ImportanceOfBeingErnest 不,不是这样。
p.sliders列表的内容仍然包含四个matplotlib.widgets.Slider实例,我仍然可以读取它们的数据。 -
好的,所以您需要提供一个可运行的代码,以便实际测试。 (目前有一些未定义的变量,所以我无法运行它)
-
我在 sliderfunc 中显示 O 和 fig undefined。奇怪的是,即使我调整滑块,我也没有得到回溯。在 ipython 和终端中的结果相同。
-
Spyder 将它们标记为错误。显然,sliderfunc 永远不会被调用。看起来 sliderfunc 和 add_slider 都有尝试更新绘图的代码。我在这里超出了我的专业领域,但无法抗拒尝试您的代码。我也使用 Anaconda python。
标签: python python-3.x matplotlib widget