Matplotlib:滑块轴外的鼠标继续改变情节

Matplotlib: mouse outside of slider axes continues to change plot

我有一个简单的脚本,可以在 x- 和 y- 中绘制数据,并且有两个滚动条。一个滚动条可让您滚动浏览 x 中的数据。第二个滚动条允许您更改在给定时间看到的 x 值的范围(下面的 SSCE)。它几乎可以正常工作:当我滑动位置滑块时,绘图会按预期滑动。滑动 'Width' 滑块可更改您看到的数据范围。

一个错误是,在我改变宽度后,当我将鼠标滚动到位置滚动条的右边缘时,它实际上一直在改变情节。动图:

我有点不知所措,我不确定为什么它会在鼠标离开滚动条轴后注册 any 事件。

相关问题
Matplotlib Updating slider widget range

重现问题的代码

%matplotlib qt 

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

x = np.arange(0, 20, 0.01)
y = np.sin(2*np.pi*x)+np.random.normal(0, 1, x.shape)
width_init = 3

delta = x[1]-x[0]
position = x[0]
final_value = x[-1]-width_init

fig, ax = plt.subplots()
plt.subplots_adjust(bottom=0.25)
plt.plot(x, y, linewidth = 0.5, color = 'grey')
plt.xlim(position, position + width_init)

# position slider
slider_pos = plt.axes([0.2, 0.1, 0.65, 0.03]) 
spos = Slider(slider_pos, 'Pos', valmin = x[0], 
              valmax = final_value, valinit = position)
# width slider
slider_width = plt.axes([0.2, 0.05, 0.5, 0.03])
swidth = Slider(slider_width, 'Width', valmin = delta*4, 
                valmax = x[-1]-delta, valinit = width_init)

def update(val):
    position = spos.val
    width = swidth.val
    slider_pos.valmin = x[0]
    slider_pos.valmax = x[-1]-width-delta
    if width < width_init:
        spos.valmax = x[-1]-width
    if position+width > x[-1]:
        spos.set_val(slider_pos.valmax)
        
    slider_pos.axes.set_xlim(slider_pos.valmin,slider_pos.valmax)   
    ax.set_xlim(position, position+width if position+width <= x[-1] else x[-1])
    fig.canvas.draw_idle()
    
spos.on_changed(update);
swidth.on_changed(update);  

您似乎混淆了代码中的滑块 spos 和滑块轴 slider_pos。您正在设置然后读取轴对象的 valmaxvalmin 属性。这不会引发错误,因为您只是在创建一个新的 属性。但是您没有正确更新实际的滑块对象。

尝试用这个替换 update 函数:

def update(val):
    position = spos.val
    width = swidth.val
    
    # Update the valmin and valmax of the spos Slider object
    spos.valmin = x[0]
    spos.valmax = x[-1]-width-delta
    if width < width_init:
        spos.valmax = x[-1]-width
    if position+width > x[-1]:
        spos.set_val(spos.valmax)
    
    # Update the slider axis to reflect the new min/max
    slider_pos.axes.set_xlim(spos.valmin,spos.valmax)   
    ax.set_xlim(position, position+width)
    fig.canvas.draw_idle()