Jupyter中使用ipywidgets如何点击按钮关闭其所属标签页
问题原因
Python闭包的迟绑定特性是问题核心:循环内定义的点击回调函数不会在定义时就保存当时的k值,只会在点击触发函数执行时才读取k的当前值,等循环执行完毕后k已经固定为最后一个标签的索引9,所以所有按钮点击都会触发关闭最后一个标签页。
此外原代码存在两处笔误:按钮变量wg_close被误写为wg_delete,标签列表tabs被误写为tab。
修复代码
import ipywidgets as widgets from ipywidgets import HBox, VBox import numpy import matplotlib.pyplot as plt from IPython.display import display %matplotlib inline tabs = [] main_tab = widgets.Tab() for k in range(10): wg_name = widgets.Text( value=str(k), placeholder='Index', description='Name:', disabled=False ) wg_close = widgets.Button( description='Close tab', ) current_tab = VBox(children=[wg_name, wg_close]) tabs.append(current_tab) # 用默认参数绑定当前循环对应的标签组件,避免迟绑定 @wg_close.on_click def close_on_click(b, target_tab=current_tab): # 从标签列表中移除目标标签 new_children = [t for t in main_tab.children if t != target_tab] main_tab.children = new_children # 同步更新标签标题 for idx, tab in enumerate(new_children): main_tab.set_title(idx, str(idx)) main_tab.children = tabs for k in range(10): main_tab.set_title(k, str(k)) main_wg = VBox(children=[main_tab]) display(main_wg)
改动说明
- 修正了原代码的变量名笔误
- 给回调函数增加
target_tab=current_tab默认参数,在定义阶段就把当前循环生成的标签组件绑定到回调里,完全规避索引迟绑定的问题,就算后续标签顺序变化也不会关错 - 关闭标签时同步更新
Tab组件的children属性和对应标题,保证界面显示和实际组件一致
内容的提问来源于stack exchange,提问作者DrTaDa
相关产品推荐
相关产品推荐

