官术网_书友最值得收藏!

Creating custom Jupyter Notebook widgets in Python, HTML, and JavaScript

The ipywidgets packages provides many built-in control widgets to interact with code and data in the Jupyter Notebook. In this recipe, we show how to build a custom interactive widget from scratch, using Python on the kernel side, and HTML/JavaScript on the client side (frontend). The widget just displays two buttons to increase and decrease a number. The number can be accessed and updated either from the kernel (Python code) or the client (browser).

How to do it...

  1. Let's import the packages:
    >>> import ipywidgets as widgets
        from traitlets import Unicode, Int, validate
  2. We create a CounterWidget class deriving from DOMWidget:
    >>> class CounterWidget(widgets.DOMWidget):
            _view_name = Unicode('CounterView').tag(sync=True)
            _view_module = Unicode('counter').tag(sync=True)
            value = Int(0).tag(sync=True)

    This class represents the Python part of the widget. The _view_name and _view_module attributes refer to the name and module of the JavaScript part. We use the traitlets package to specify the type of the variables. The value attribute is the counter value, an integer initialized at 0. All of these attributes' values are synchronized between Python and JavaScript, hence the sync=True option.

  3. We now turn to the JavaScript side of the widget. We can write the code directly in the notebook using the %%javascript cell magic. The widget framework relies on several JavaScript libraries: jQuery (represented as the $ variable), RequireJS (modules and dependencies), and Backbone.js (a model view controller framework):
    >>> %%javascript
        // We make sure the 'counter' module is defined
        // only once.
        require.undef('counter');
        
        // We define the 'counter' module depending on the
        // Jupyter widgets framework.
        define('counter', ["@jupyter-widgets/base"],
               function(widgets) {
        
            // We create the CounterView frontend class,
            // deriving from DOMWidgetView.
            var CounterView = widgets.DOMWidgetView.extend({
        
                // This method creates the HTML widget.
                render: function() {
                    // The value_changed() method should be
                    // called when the model's value changes
                    // on the kernel side.
                    this.value_changed();
                    this.model.on('change:value',
                                  this.value_changed, this);
        
                    var model = this.model;
                    var that = this;
        
                    // We create the plus and minus buttons.
                    this.bm = $('<button/>')
                    .text('-')
                    .click(function() {
                        // When the button is clicked,
                        // the model's value is updated.
                        var x = model.get('value');
                        model.set('value', x - 1);
                        that.touch();
                    });
        
                    this.bp = $('<button/>')
                    .text('+')
                    .click(function() {
                        var x = model.get('value');
                        model.set('value', x + 1);
                        that.touch();
                    });
        
                    // This element displays the current
                    // value of the counter.
                    this.span = $('<span />')
                    .text('0')
                    .css({marginLeft: '10px',
                          marginRight: '10px'});
        
                    // this.el represents the widget's DOM
                    // element. We add the minus button,
                    // the span element, and the plus button.
                    $(this.el)
                    .append(this.bm)
                    .append(this.span)
                    .append(this.bp);
                },
        
                value_changed: function() {
                    // Update the displayed number when the
                    // counter's value changes.
                    var x = this.model.get('value');
                    $($(this.el).children()[1]).text(x);
                },
            });
        
            return {
                CounterView : CounterView
            };
        });
  4. Let's display the widget:
    >>> w = CounterWidget()
        w
    How to do it...
  5. Pressing the buttons updates the value immediately.
    How to do it...

    Custom widget

  6. The counter's value is automatically updated on the kernel side:
    >>> print(w.value)
    4
  7. Conversely, we can update the value from Python, and it is updated in the frontend:
    >>> w.value = 5
    How to do it...

There's more...

Here are a few references:

See also

  • The Mastering widgets in the Jupyter Notebook recipe
主站蜘蛛池模板: 彰武县| 个旧市| 阿克苏市| 牟定县| 三河市| 三亚市| 昌吉市| 瑞安市| 连平县| 牟定县| 永济市| 洪泽县| 文登市| 京山县| 永善县| 萨迦县| 景洪市| 昭觉县| 尼木县| 翁源县| 兴义市| 犍为县| 延安市| 砚山县| 普陀区| 杭锦后旗| 凌海市| 巴楚县| 咸宁市| 桐庐县| 武乡县| 富民县| 乌兰县| 安吉县| 崇信县| 大埔县| 丹东市| 区。| 福鼎市| 焦作市| 谢通门县|