从容器中的多个 ipywidgets 卸载值

Unloading values from multiple ipywidgets in a container

我刚开始使用 ipywidgets,我正在尝试找到诀窍,所以如果这个问题之前已经回答过或者文档以某种方式涵盖了它,请指点我到那个部分。本质上,这是我正在尝试开发的 UI 的微型版本。

让我困惑的问题是,一旦我构建了一个如下所示的UI,并且用户提供了他们的输入,我该如何卸载输入?我希望为每个变量收集值并触发我的逻辑,但我在文档中看到的唯一内容是使用交互或交互。

但是我不太确定如何将它们与多个小部件一起使用,我遇到的所有示例似乎都指向将它们与单个小部件一起使用。如果有人能给我指出好的资源或提供示例,那将很有帮助。

有了那个分类器,我想做的是:

import ipywidgets as widgets
style = {'description_width': 'initial'}

def input_tab(tab_list, tab_names_list):
    if len(tab_list) == len(tab_names_list):
        this_tab = Tab()
        this_tab.children = tab_list
        [this_tab.set_title(i, title) for i, title in enumerate(tab_names_list)]
        return this_tab
    else:
        raise ValueError('\n Input lists should be of the same size')

def get_input_panel_num():
    input_1 = widgets.Text(value='3000', description='Input-1', style=style)
    input_2 = widgets.Dropdown(options=['yes', 'no'], description='Select one', value='yes', disabled=False, style=style)
    input_3 = widgets.IntSlider(value=0, min=0, max=1, step=1, description='Input-3', orientation='horizontal', readout=True, 
                               style=style)
    input_list_num = [input_1, input_2, input_3]
    return input_list_num

def get_input_panel_char():
    input_a = widgets.Text(value='3000', description='Input-1', style=style)
    input_b = widgets.Dropdown(options=['yes', 'no'], description='Select one', value='yes', disabled=False, style=style)
    input_c = widgets.IntSlider(value=0, min=0, max=1, step=1, description='Input-3', orientation='horizontal', readout=True, 
                               style=style)
    input_list_char = [input_a, input_b, input_c]
    return input_list_char

def create_master_tab():
    tab_names = ["tab-1", "tab-2"]
    panel_num = VBox(get_input_panel_num())
    panel_char = VBox(get_input_panel_char())
    final = input_tab(tab_list=[panel_num, panel_char], tab_names_list=tab_names)
    return final

demo = create_master_tab()
demo 

***************** 更新的问题 *************************** *** @ac24: 我无法 post 评论中的所有代码,所以这是我在采纳您的建议后更新的代码。它在很大程度上按预期运行,但拒绝接受让我感到困惑的标题。我可以使用完全相同的方法为选项卡设置标题,所以我不确定真正发生了什么变化:

import ipywidgets as widgets 
from ipywidgets import HBox
from ipywidgets import Tab 


# Definition of style
style = {'description_width': 'initial'}


class TabHolder(Tab):
    def __init__(self, tab_objects, tab_names):
        """
        Initialization of TabHolder object class

        :param list tab_objects: collection of display objects to be captured in the tabs
        :param list tab_names: names to assign to the tabs
        :return: tab widget containing all the tabs
        :rtype: Tab
        """

        if len(tab_names) != len(tab_objects):
            raise ValueError("\n Failed in TabHolder creation, because of lengths of inputs don't match")
        else:
            self.tab = Tab()
            self.tab_names = tab_names
            self.tab_objects = tab_objects
            self.inputs = []
            for i in tab_objects:
                self.inputs.append(i)
            super().__init__(children=self.inputs)
            [self.tab.set_title(i, title) for i, title in enumerate(self.tab_names)]  # Why titles not being set?


class InputPanelChar(HBox):

    def __init__(self):
        self.input_a = widgets.Text(value='3000', description='Input-1', style=style)
        self.input_b = widgets.Dropdown(options=['yes', 'no'], description='Select one', value='yes', disabled=False,
                                        style=style)
        self.input_c = widgets.IntSlider(value=0, min=0, max=1, step=1, description='Input-3', orientation='horizontal',
                                         readout=True, style=style)
        self.input_list_char = [self.input_a, self.input_b, self.input_c]
        super().__init__(children= self.input_list_char)

    def get_interact_value(self):
        return {
            w.description: w.get_interact_value()
            for w in self.input_list_char
        }


class InputPanelNum(HBox):

    def __init__(self):
        self.input_1 = widgets.Text(value='3000', description='Input-1', style=style)
        self.input_2 = widgets.Dropdown(options=['yes', 'no'], description='Select one', value='yes', disabled=False,
                                        style=style)
        self.input_3 = widgets.IntSlider(value=0, min=0, max=1, step=1, description='Input-3', orientation='horizontal',
                                         readout=True, style=style)
        self.input_list_num = [self.input_1, self.input_2, self.input_3]
        super().__init__(children= self.input_list_num)

    def get_interact_value(self):
        return {
            w.description: w.get_interact_value()
            for w in self.input_list_num
        }

经历过完全相同的问题后,我的解决方案是开发 类 一起有意义的小部件组。

如果将各种函数转换为 类,则可以提取各种小部件值。我已将您的 input_panel_char 函数改编为 HBox 的子类。

我假设您想将小部件值作为字典获取,以小部件描述作为键。

class InputPanelChar(widgets.HBox):

    def __init__(self):
        self.input_a = widgets.Text(value='3000', description='Input-1', style=style)
        self.input_b = widgets.Dropdown(options=['yes', 'no'], description='Select one', value='yes', disabled=False, style=style)
        self.input_c = widgets.IntSlider(value=0, min=0, max=1, step=1, description='Input-3', orientation='horizontal', readout=True, 
                               style=style)
        self.input_list_char = [self.input_a, self.input_b, self.input_c]
        super().__init__(children= self.input_list_char)

    def get_interact_value(self):
        return {
            w.description: w.get_interact_value()
            for w in self.input_list_char
        }

*****更新*****

在创建标签持有者时,您将 Tab 子类化并创建标签实例,这会导致混淆。您需要做的就是子类 Tab,然后 self 是一个 Tab 实例,无需在您的实例中创建 self.tabs。希望这个例子很清楚:


class TabHolder(Tab):
    def __init__(self, tab_objects, tab_names):

        if len(tab_names) != len(tab_objects):
            raise ValueError("\n Failed in TabHolder creation, because of lengths of inputs don't match")
        else:
            self.tab_names = list(tab_names)
            self.tab_objects = list(tab_objects)
            super().__init__(children=self.tab_objects)
            for i, title in enumerate(self.tab_names):
                self.set_title(i, title)