0

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観測された関数を設定すると、数値の変更時とオプション値の変更時に 2 回呼び出されます。

2番目に最悪なのは、次のようなBoxウィジェットでこのウィジェットを使用できないことです。

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

発生するもの:

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

より良い解決策はありますか?

4

2 に答える 2