ipywidgets中FloatSlider控件游标无法移动问题求助
问题原因
滑块卡死的核心原因是绘图函数内的while循环逻辑存在漏洞,特定参数下会触发死循环:
- 代入参数可计算出油滴的终端速度约为
6e-5 m/s,而你设置的v_0滑块最大值为10e-5,覆盖了初始速度超过终端速度的场景 - 现有循环判断条件
v[-1] < (1-1e-4)*m*g/b or n_i < 100仅适配初始速度小于终端速度的场景:当初始速度大于终端速度时,油滴速度会从高值逐渐下降到终端速度,v[-1] < 阈值的条件永远成立,or逻辑会让循环持续执行,直接卡死交互进程。
修复方案
调整while循环的判断逻辑,兼容速度从上下两个方向趋近终端速度的场景,同时增加最大迭代次数上限避免极端情况卡死;建议将固定参数移到函数外预先计算,减少重复计算提升交互流畅度。
修复后完整代码
import numpy as np import matplotlib.pyplot as plt import matplotlib.gridspec as gridspec import ipywidgets as widgets import matplotlib.ticker as mtick # 预先计算固定常量,避免每次调用函数重复计算 D = 1.5e-6 # 油滴直径 [m] rho = 840 # 液体密度 [kg/m^3] g = 9.8 # 重力加速度 [m/s^2] V = np.pi/6*D**3 # 油滴体积 [m^3] m = rho*V # 颗粒质量 [kg] beta = 1.6e-4 # 空气动力粘度 [kg/ms] b = beta*D # 线性摩擦系数 [kg/s] v_terminal = m*g/b # 终端速度 error_thres = 1e-4 # 稳态误差阈值 max_iter = 10000 # 最大迭代次数兜底,彻底避免死循环 def plot_2_2(v_0=0,dt=7e-7): t_0 = 0 # 初始时间 [s] n_i = 0 # 迭代次数计数 fig = plt.figure(constrained_layout=True, figsize=[14,8]) spec = gridspec.GridSpec(ncols=1,nrows=2,figure=fig) ax1 = fig.add_subplot(spec[0,0]) ax2 = fig.add_subplot(spec[1,0]) t = [t_0] v = [v_0] # 修复后的循环条件:相对误差未达标 且 未超过最大迭代次数时继续执行 while abs(v[-1] - v_terminal)/v_terminal > error_thres and n_i < max_iter: t.append(t[-1]+dt) v.append(v[-1]+(m*g-b*v[-1])*(dt)/m) n_i += 1 t = np.array(t) v = np.array(v) v_analytic = v_0*np.exp(-b/m*t) + v_terminal*(1-np.exp(-b/m*t)) # 解析解 l11, = ax1.plot(t,v,'r--') # 数值解 l12, = ax1.plot(t, v_analytic,'kx') l2, = ax2.plot(t,100*abs(v - v_analytic)/v_analytic,'c--') # 相对误差 ax1.set_xlabel('时间 [s]') ax1.set_ylabel('油滴速度 [m/s]') ax1.set_ylim(bottom=-0.5e-4,top=1.5e-4) ax1.ticklabel_format(axis="y", style="sci", scilimits=(0,0)) ax1.set_title("油滴速度演变") ax1.grid(linestyle='-.') ax2.yaxis.set_major_formatter(mtick.PercentFormatter()) ax2.set_xlabel('时间 [s]') ax2.set_ylabel('相对误差') ax2.set_title("数值解 vs 解析解") ax2.grid(linestyle='-.') plt.show(fig) widgets.interact(plot_2_2, v_0=widgets.FloatSlider(min=0,max=10e-5,step=1e-5,readout_format='.1e'), dt=widgets.FloatSlider(min=5e-7,max=10e-7,step=1e-7,readout_format='.1e'))
额外优化建议
运行代码前先执行%matplotlib widget魔法命令,可大幅提升matplotlib交互场景的流畅度。
内容的提问来源于stack exchange,提问作者Lucas Cruz
相关产品推荐
相关产品推荐

