2016-11-14 55 views
0

比方說,我想要一個由IntText小部件和DropDown小部件組成的小部件,該小部件的值是這些小部件值的連接字符串。我能怎麼做?如何從多個創建ipywidgets?

下面是一個嘗試:

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時,觀察到的功能被調用兩次:關於數值變化和選項值變化。

第二,最糟糕的是,我不能在一個盒子插件一樣使用此插件:

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

這就提出:

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

有沒有更好的解決辦法?

回答

0

可能有一個原因,你爲什麼去創建一個新的小部件的麻煩,但爲什麼不使用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的返回值,這就是你要找的人...

0
  1. 你創建的類2個部件的連接字符串使用關鍵字參數是不是一個widget ,儘管你確實模仿了一些行爲(observe,display)。這可能是爲什麼你無法在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)