【问题标题】:How to create a ipywidgets from multiple ones?如何从多个 ipywidgets 创建一个 ipywidgets?
【发布时间】:2016-11-14 17:20:44
【问题描述】:

假设我想要一个由 IntText 小部件和 DropDown 小部件组成的小部件,其值是这些小部件值的串联字符串。我该怎么办?

这是一个尝试:

import re
import ipywidgets as ipw

from IPython.display import display


class IntMultipliedDropdown:
    _VALUE_PATTERN = re.compile('(?P<num>\d+) (?P<option>\w+-?\w*)')

    def __init__(self, options, option_value, int_value=1):
        self.number = ipw.IntText(int_value)
        self.options = ipw.Dropdown(options=options, value=option_value)
        self.box = ipw.HBox([self.number, self.options])

        self.number.observe(self._on_changes, names='value')
        self.options.observe(self._on_changes, names='value')

        self._handelers = []

    def _on_changes(self, change):
        for handeler in self._handelers:
            handeler(self.value)

    @property
    def value(self):
        return "{} {}".format(self.number.value, self.options.value)

    @value.setter
    def value(self, value):
        match = re.search(self._VALUE_PATTERN, value)
        groupdict = match.groupdict()
        self.number.value = groupdict['num']
        self.options.value = groupdict['option']

    def _ipython_display_(self, **kwargs):
        return self.box._ipython_display_(**kwargs)

    def observe(self, handler):
        if handler not in self._handelers:
            self._handelers.append(handler)


mywidget = IntMultipliedDropdown(['apple', 'bed', 'cell'], 'cell')
mywidget.observe(print)

display(mywidget)
print('default value:', mywidget.value)

mywidget.value = '2 bed'

它有效但有缺点。首先,当我设置mywidget.value 时,观察到的函数会被调用两次:数值变化和选项值变化。

第二个也是最糟糕的是我不能在 Box 小部件中使用这个小部件,例如:

ipw.HBox([ipw.Label('Mylabel'), mywidget])

引发:

ValueError: Can't clean for JSON: <__main__.IntMultipliedDropdown object at 0x7f7d604fff28>

有没有更好的解决方案?

【问题讨论】:

    标签: python jupyter-notebook ipywidgets


    【解决方案1】:
    1. 您创建的类不是小部件,尽管您确实模仿了一些行为(observedisplay)。这可能就是您无法在HBox 中显示它的原因。如果您想创建一个新的小部件,请从 ipyw.Widget 或任何其他小部件继承。
    2. 您有两个正在监听的底层小部件,因此当您更改它们的值时调用两个函数是正常的。如果您只想调用一个函数,请直接收听新小部件的 value

    这就是你可以做到的,通过继承HBox

    import re
    import ipywidgets as ipw
    from traitlets import Unicode
    from IPython.display import display
    
    
    class IntMultipliedDropdown(ipw.HBox):
        _VALUE_PATTERN = re.compile('(?P<num>\d+) (?P<option>\w+-?\w*)')
        value = Unicode()
    
        def __init__(self, options, option_value, int_value=1, **kwargs):
            self.number = ipw.IntText(int_value)
            self.options = ipw.Dropdown(options=options, value=option_value)
    
            self._update_value()
    
            self.number.observe(self._update_value, names='value')
            self.options.observe(self._update_value, names='value')
            self.observe(self._update_children, names='value')
    
            super().__init__(children=[self.number, self.options], **kwargs)
    
    
        def _update_children(self, *args):
            match = re.search(self._VALUE_PATTERN, self.value)
            groupdict = match.groupdict()
            self.number.value = groupdict['num']
            self.options.value = groupdict['option']
    
        def _update_value(self, *args):
            self.value = "{} {}".format(self.number.value, self.options.value)
    
    mywidget = IntMultipliedDropdown(['apple', 'bed', 'cell'], 'cell')
    display(mywidget)
    

    【讨论】:

    • 为了工作:super(IntMultipliedDropdown, self)
    • 我尝试不使用 _update_value 函数并且一切正常,这至关重要的是 _update_children 函数,顺便说一下,这会更好:_update_children(self, change) 如文档所示(@987654321 @)
    【解决方案2】:

    您费尽心思创建新小部件可能是有原因的,但为什么不使用the interactive function

    类似:

    import ipywidgets as ipw
    from ipywidgets import *
    
    w_number = ipw.IntText(value = 1)
    w_options = ipw.Dropdown(options = ['apple', 'bed', 'cell'], value ='cell')
    
    mywidget_value = ''
    
    def display_value(number, options):
        mywidget_value = str(number)+' '+options
        #print(mywidget_value)
        return mywidget_value
    
    w_box = interactive(display_value, number=w_number, options=w_options)
    
    display(w_box)
    

    然后你有一个Box,你可以调整它的布局。您还可以使用 w_box.kwargs 访问关键字参数或使用 w_box.result 访问函数的返回值,这是您正在寻找的 2 个小部件的串联字符串...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-26
      相关资源
      最近更新 更多