在 for 循环中创建函数来控制 ToggleButton,后期绑定问题ipywidgets JupyterLab

问题描述

我正在尝试为我的情节制作 ToggleButtons 并偶然发现一个问题。我创建了按钮,没问题:

# create buttons
button = []
for i in range(len(expnum)):
    button.append(wg.ToggleButton(value=False,description=expnum[i],tooltip='Click to show/hide',layout=wg.Layout(width='60px',height='30px')))
    button.append(wg.Output())

问题是这部分:

# control buttons
for i in range(len(expnum)):
    def on_value_change(change):
        with button[i * 2 + 1]:
            plots[i][0].set_visible(change['new'])
    button[i * 2].observe(on_value_change,names='value')

代码的问题是(我猜)后期绑定问题。它只识别最后一个值(意思是:仅在 i == len(expnum)-1 的状态下),这不是我所期望的。实际上,我使用以下代码成功地使其按照我的预期工作:

# control buttons
def on_value_change(change):
    with button[1]:
        plots[0][0].set_visible(change['new'])
button[0].observe(on_value_change,names='value')    
    
def on_value_change(change):
    with button[3]:
        plots[1][0].set_visible(change['new'])
button[2].observe(on_value_change,names='value')

def on_value_change(change):
    with button[5]:
        plots[2][0].set_visible(change['new'])
button[4].observe(on_value_change,names='value')

等等。目前手动这样写迭代次数还是可以管理的,但是随着数据量的增加,不使用for循环是不可能的。

我对 python 有点陌生,我很确定必须有某种简单的 hack 或解决方法才能使这件事起作用。我发现一些线程解释了如何强制使用 def f(i=i): 而不仅仅是 def f(): 进行早期绑定。但我不知道如何将这些应用到我的案例中。 有谁知道如何用 for 循环解决我的问题?否则,也欢迎采用全新的方法

--- 编辑---

这是完整的代码

import pandas as pd
import numpy as np
import ipywidgets as wg
from ipywidgets import HBox,VBox
import matplotlib.pyplot as plt
import matplotlib
from IPython.display import display
%matplotlib widget

expnum = ['data1','data2','data3']
t_all = [ [1,2,3],[1,3,4],5] ]
V_all = [ [100,200,100],[100,120,130],[150,105,100] ]

# create buttons
button = []
for i in range(len(expnum)):
    button.append(wg.ToggleButton(value=False,height='30px')))
    button.append(wg.Output())
display(HBox(( [button[i] for i in range(len(button))] )) )

# create figure
fig,ax = plt.subplots()
ax.set_xlabel('t [s]')
ax.set_ylabel('V [V]')

plots = []
for i in range(len(t_all)):
    plots.append(ax.plot(t_all[i],V_all[i],visible=False,alpha=0.7))    

# ---------------- The problem starts here --------------------------    
# set visibility of plots
for i in range(len(expnum)):
    def on_value_change(change):
        with button[i * 2 + 1]:
            plots[i][0].set_visible(change['new'])
    button[i * 2].observe(on_value_change,names='value')

为什么上面的代码(从 # set visibility of plots 开始)不起作用,而下面的代码起作用:

def on_value_change(change):
    with button[1]:
        plots[0][0].set_visible(change['new'])
button[0].observe(on_value_change,names='value')   

除了使用 for 循环而不是一遍又一遍地手动重新键入相同的代码之外,我认为下面的代码和上面的代码没有区别。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)