Matplotlib 根据另一个滑块的变化更新一个滑块
Matplotlib update one slider based on change in another slider
我使用 matplotlib 生成一个简单的绘图,其中有 2 个滑块控制绘图上的移动点 - 向用户展示 x 或 y 的变化如何影响点的位置。我需要这些滑块来彼此共享信息——如果一个滑块发生变化,另一个滑块会根据更改后的值更新其值(例如,如果控制 x 的滑块发生变化,则控制 y 的滑块也会更新,反之亦然)。
我在 Whosebug 上对此进行了研究,并尝试实施两种解决方案(第一次尝试在下面的代码中被注释掉)但没有成功。我尝试的最后一次迭代似乎有效,但过了一会儿它冻结了情节。
我的代码是:
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)
# Define x values and y function, y = f(2x**2)
x = np.arange(0.0, 11., 1.)
y = x**2
fxplot, = plt.plot(x, y, lw=2)
#define the bullet point to slide on the function
x0=2.
y0=x0**2
x0_old = x0
y0_old = y0
ptplot, = plt.plot(x0, y0, 'ko')
# Define the sliders
axcolor = 'lightgoldenrodyellow'
ax_x = plt.axes([0.25, 0.15, 0.65, 0.03], facecolor=axcolor)
ax_y = plt.axes([0.25, 0.1, 0.65, 0.03], facecolor=axcolor)
xSlider = Slider(ax_x, 'x', 0.0, 10.0, valinit=x0, valstep=1)
ySlider = Slider(ax_y, 'y', 0.0, 10.0**2, valinit=y0, valstep=1)
# Update function; movement of one slider updates the other
# by reinitializing it
def update(val):
global x0_old, y0_old
x0 = xSlider.val
y0 = ySlider.val
# Detect change in y0
if x0 == x0_old:
print('y0 changed',y0,y0_old)
ptplot.set_xdata(np.sqrt(y0))
ptplot.set_ydata(y0)
y0_old = y0
## ax_x.clear()
## xSlider.__init__(ax_x, 'x', 0.0, 10.0, valinit=np.sqrt(y0), valstep=1)
xSlider.valinit = np.sqrt(y0)
xSlider.reset()
# Detect change in x0
if y0 == y0_old:
print('x0 changed',x0,x0_old)
ptplot.set_xdata(x0)
ptplot.set_ydata(x0**2)
x0_old = x0
## ax_y.clear()
## ySlider.__init__(ax_y, 'y', 0.0, 10.0**2, valinit=y0, valstep=1)
ySlider.valinit = x0**2
ySlider.reset()
print('\n')
plt.gcf().canvas.draw_idle()
xSlider.on_changed(update)
ySlider.on_changed(update)
plt.show()
我希望这是一个简单的修复,但不幸的是,我看不到它,我希望有更多使用滑块经验的人能够提供帮助。
提前致谢。
最明显的解决方案是调用 Slider.set_val()
,但是,这会产生无限递归错误,因为调用 set_val()
会触发回调,调用 set_val()
,等等...
幸运的是,可以通过使用 the (undocumented) property Widget.eventson
指示小部件不调用回调函数来防止错误
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)
# Define x values and y function, y = f(2x**2)
x = np.arange(0.0, 11., 1.)
f = lambda x: x**2
g = lambda x: np.sqrt(x)
y = f(x)
fxplot, = plt.plot(x, y, lw=2)
#define the bullet point to slide on the function
x0=2.
y0=f(x0)
ptplot, = plt.plot(x0, y0, 'ko')
# Define the sliders
axcolor = 'lightgoldenrodyellow'
ax_x = plt.axes([0.25, 0.15, 0.65, 0.03], facecolor=axcolor)
ax_y = plt.axes([0.25, 0.1, 0.65, 0.03], facecolor=axcolor)
xSlider = Slider(ax_x, 'x', 0.0, 10.0, valinit=x0, valstep=1)
ySlider = Slider(ax_y, 'y', f(0.0), f(10.0), valinit=y0, valstep=1)
def update_x(x):
y = f(x)
ptplot.set_data(x, y)
ySlider.eventson = False
ySlider.set_val(y)
fig.canvas.draw()
ySlider.eventson = True
def update_y(y):
x = g(y)
ptplot.set_data(x, y)
xSlider.eventson = False
xSlider.set_val(x)
fig.canvas.draw()
xSlider.eventson = True
xSlider.on_changed(update_x)
ySlider.on_changed(update_y)
plt.show()
我使用 matplotlib 生成一个简单的绘图,其中有 2 个滑块控制绘图上的移动点 - 向用户展示 x 或 y 的变化如何影响点的位置。我需要这些滑块来彼此共享信息——如果一个滑块发生变化,另一个滑块会根据更改后的值更新其值(例如,如果控制 x 的滑块发生变化,则控制 y 的滑块也会更新,反之亦然)。
我在 Whosebug 上对此进行了研究,并尝试实施两种解决方案(第一次尝试在下面的代码中被注释掉)但没有成功。我尝试的最后一次迭代似乎有效,但过了一会儿它冻结了情节。
我的代码是:
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)
# Define x values and y function, y = f(2x**2)
x = np.arange(0.0, 11., 1.)
y = x**2
fxplot, = plt.plot(x, y, lw=2)
#define the bullet point to slide on the function
x0=2.
y0=x0**2
x0_old = x0
y0_old = y0
ptplot, = plt.plot(x0, y0, 'ko')
# Define the sliders
axcolor = 'lightgoldenrodyellow'
ax_x = plt.axes([0.25, 0.15, 0.65, 0.03], facecolor=axcolor)
ax_y = plt.axes([0.25, 0.1, 0.65, 0.03], facecolor=axcolor)
xSlider = Slider(ax_x, 'x', 0.0, 10.0, valinit=x0, valstep=1)
ySlider = Slider(ax_y, 'y', 0.0, 10.0**2, valinit=y0, valstep=1)
# Update function; movement of one slider updates the other
# by reinitializing it
def update(val):
global x0_old, y0_old
x0 = xSlider.val
y0 = ySlider.val
# Detect change in y0
if x0 == x0_old:
print('y0 changed',y0,y0_old)
ptplot.set_xdata(np.sqrt(y0))
ptplot.set_ydata(y0)
y0_old = y0
## ax_x.clear()
## xSlider.__init__(ax_x, 'x', 0.0, 10.0, valinit=np.sqrt(y0), valstep=1)
xSlider.valinit = np.sqrt(y0)
xSlider.reset()
# Detect change in x0
if y0 == y0_old:
print('x0 changed',x0,x0_old)
ptplot.set_xdata(x0)
ptplot.set_ydata(x0**2)
x0_old = x0
## ax_y.clear()
## ySlider.__init__(ax_y, 'y', 0.0, 10.0**2, valinit=y0, valstep=1)
ySlider.valinit = x0**2
ySlider.reset()
print('\n')
plt.gcf().canvas.draw_idle()
xSlider.on_changed(update)
ySlider.on_changed(update)
plt.show()
我希望这是一个简单的修复,但不幸的是,我看不到它,我希望有更多使用滑块经验的人能够提供帮助。
提前致谢。
最明显的解决方案是调用 Slider.set_val()
,但是,这会产生无限递归错误,因为调用 set_val()
会触发回调,调用 set_val()
,等等...
幸运的是,可以通过使用 the (undocumented) property Widget.eventson
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)
# Define x values and y function, y = f(2x**2)
x = np.arange(0.0, 11., 1.)
f = lambda x: x**2
g = lambda x: np.sqrt(x)
y = f(x)
fxplot, = plt.plot(x, y, lw=2)
#define the bullet point to slide on the function
x0=2.
y0=f(x0)
ptplot, = plt.plot(x0, y0, 'ko')
# Define the sliders
axcolor = 'lightgoldenrodyellow'
ax_x = plt.axes([0.25, 0.15, 0.65, 0.03], facecolor=axcolor)
ax_y = plt.axes([0.25, 0.1, 0.65, 0.03], facecolor=axcolor)
xSlider = Slider(ax_x, 'x', 0.0, 10.0, valinit=x0, valstep=1)
ySlider = Slider(ax_y, 'y', f(0.0), f(10.0), valinit=y0, valstep=1)
def update_x(x):
y = f(x)
ptplot.set_data(x, y)
ySlider.eventson = False
ySlider.set_val(y)
fig.canvas.draw()
ySlider.eventson = True
def update_y(y):
x = g(y)
ptplot.set_data(x, y)
xSlider.eventson = False
xSlider.set_val(x)
fig.canvas.draw()
xSlider.eventson = True
xSlider.on_changed(update_x)
ySlider.on_changed(update_y)
plt.show()