##// END OF EJS Templates
Update examples, fixing bugs found in review.
Jonathan Frederic -
Show More
@@ -1,797 +1,796 b''
1 1 {
2 2 "metadata": {
3 "celltoolbar": "Slideshow",
4 3 "kernelspec": {
5 4 "codemirror_mode": {
6 5 "name": "python",
7 6 "version": 2
8 7 },
9 8 "display_name": "Python 2",
10 9 "language": "python",
11 10 "name": "python2"
12 11 },
13 12 "name": "",
14 "signature": "sha256:ebbb9b368e8b07ec14fd5ee494586e605be36631657f2a9d9a6475ead41a3e04"
13 "signature": "sha256:608e0df06fe91ef1c013fd236dda33f7ae11019453f72ae446e8ce15bce82eb2"
15 14 },
16 15 "nbformat": 3,
17 16 "nbformat_minor": 0,
18 17 "worksheets": [
19 18 {
20 19 "cells": [
21 20 {
22 21 "cell_type": "markdown",
23 22 "metadata": {},
24 23 "source": [
25 24 "[Index](Index.ipynb) - [Back](Widget Styling.ipynb)"
26 25 ]
27 26 },
28 27 {
29 28 "cell_type": "code",
30 29 "collapsed": false,
31 30 "input": [
32 31 "from __future__ import print_function # For py 2.7 compat"
33 32 ],
34 33 "language": "python",
35 34 "metadata": {},
36 35 "outputs": []
37 36 },
38 37 {
39 38 "cell_type": "heading",
40 39 "level": 1,
41 40 "metadata": {
42 41 "slideshow": {
43 42 "slide_type": "slide"
44 43 }
45 44 },
46 45 "source": [
47 46 "Building a Custom Widget"
48 47 ]
49 48 },
50 49 {
51 50 "cell_type": "markdown",
52 51 "metadata": {},
53 52 "source": [
54 53 "The widget framework is built **on top of the Comm framework** (short for communication). The Comm framework is a framework that **allows you send/receive JSON messages** to/from the front-end (as seen below).\n",
55 54 "\n",
56 55 "![Widget layer](images/WidgetArch.png)\n",
57 56 "\n",
58 57 "To create a custom widget, you need to **define the widget both in the back-end and in the front-end**. "
59 58 ]
60 59 },
61 60 {
62 61 "cell_type": "heading",
63 62 "level": 1,
64 63 "metadata": {
65 64 "slideshow": {
66 65 "slide_type": "slide"
67 66 }
68 67 },
69 68 "source": [
70 69 "Building a Custom Widget"
71 70 ]
72 71 },
73 72 {
74 73 "cell_type": "markdown",
75 74 "metadata": {},
76 75 "source": [
77 76 "To get started, you'll create a **simple hello world widget**. Later you'll build on this foundation to make more complex widgets."
78 77 ]
79 78 },
80 79 {
81 80 "cell_type": "heading",
82 81 "level": 2,
83 82 "metadata": {
84 83 "slideshow": {
85 84 "slide_type": "slide"
86 85 }
87 86 },
88 87 "source": [
89 88 "Back-end (Python)"
90 89 ]
91 90 },
92 91 {
93 92 "cell_type": "heading",
94 93 "level": 3,
95 94 "metadata": {},
96 95 "source": [
97 96 "DOMWidget and Widget"
98 97 ]
99 98 },
100 99 {
101 100 "cell_type": "markdown",
102 101 "metadata": {},
103 102 "source": [
104 103 "To define a widget, you must inherit from the **Widget or DOMWidget** base class. If you intend for your widget to be **displayed in the IPython notebook**, you'll need to **inherit from the DOMWidget**. The DOMWidget class itself inherits from the Widget class. The Widget class is useful for cases in which the **Widget is not meant to be displayed directly in the notebook**, but **instead as a child of another rendering environment**. For example, if you wanted to create a three.js widget (a popular WebGL library), you would implement the rendering window as a DOMWidget and any 3D objects or lights meant to be rendered in that window as Widgets."
105 104 ]
106 105 },
107 106 {
108 107 "cell_type": "heading",
109 108 "level": 3,
110 109 "metadata": {
111 110 "slideshow": {
112 111 "slide_type": "slide"
113 112 }
114 113 },
115 114 "source": [
116 115 "_view_name"
117 116 ]
118 117 },
119 118 {
120 119 "cell_type": "markdown",
121 120 "metadata": {},
122 121 "source": [
123 122 "Inheriting from the DOMWidget does not tell the widget framework what front-end widget to associate with your back-end widget. Instead, you must tell it yourself by defining a **specially named Traitlet, `_view_name`** (as seen below)."
124 123 ]
125 124 },
126 125 {
127 126 "cell_type": "code",
128 127 "collapsed": false,
129 128 "input": [
130 129 "from IPython.html import widgets\n",
131 130 "from IPython.utils.traitlets import Unicode\n",
132 131 "\n",
133 132 "class HelloWidget(widgets.DOMWidget):\n",
134 133 " _view_name = Unicode('HelloView', sync=True)"
135 134 ],
136 135 "language": "python",
137 136 "metadata": {},
138 137 "outputs": []
139 138 },
140 139 {
141 140 "cell_type": "heading",
142 141 "level": 3,
143 142 "metadata": {
144 143 "slideshow": {
145 144 "slide_type": "slide"
146 145 }
147 146 },
148 147 "source": [
149 148 "sync=True traitlets"
150 149 ]
151 150 },
152 151 {
153 152 "cell_type": "markdown",
154 153 "metadata": {},
155 154 "source": [
156 155 "**Traitlets is** an IPython library for defining **type-safe properties** on configurable objects. For this tutorial you do not need to worry about the *configurable* piece of the traitlets machinery. The **`sync=True` keyword argument** tells the widget framework to **handle synchronizing that value to the front-end**. Without `sync=True`, the front-end would have no knowledge of `_view_name`."
157 156 ]
158 157 },
159 158 {
160 159 "cell_type": "heading",
161 160 "level": 3,
162 161 "metadata": {
163 162 "slideshow": {
164 163 "slide_type": "slide"
165 164 }
166 165 },
167 166 "source": [
168 167 "Other traitlet types"
169 168 ]
170 169 },
171 170 {
172 171 "cell_type": "markdown",
173 172 "metadata": {},
174 173 "source": [
175 174 "Unicode, used for _view_name, is not the only Traitlet type, there are many more some of which are listed below: \n",
176 175 "\n",
177 176 "- Any\n",
178 177 "- Bool\n",
179 178 "- Bytes\n",
180 179 "- CBool\n",
181 180 "- CBytes\n",
182 181 "- CComplex\n",
183 182 "- CFloat\n",
184 183 "- CInt\n",
185 184 "- CLong\n",
186 185 "- CRegExp\n",
187 186 "- CUnicode\n",
188 187 "- CaselessStrEnum\n",
189 188 "- Complex\n",
190 189 "- Dict\n",
191 190 "- DottedObjectName\n",
192 191 "- Enum\n",
193 192 "- Float\n",
194 193 "- FunctionType\n",
195 194 "- Instance\n",
196 195 "- InstanceType\n",
197 196 "- Int\n",
198 197 "- List\n",
199 198 "- Long\n",
200 199 "- Set\n",
201 200 "- TCPAddress\n",
202 201 "- Tuple\n",
203 202 "- Type\n",
204 203 "- Unicode\n",
205 204 "\n",
206 205 "**Not all of these traitlets can be synchronized** across the network, **only the JSON-able** traits and **Widget instances** will be synchronized."
207 206 ]
208 207 },
209 208 {
210 209 "cell_type": "heading",
211 210 "level": 2,
212 211 "metadata": {
213 212 "slideshow": {
214 213 "slide_type": "slide"
215 214 }
216 215 },
217 216 "source": [
218 217 "Front-end (JavaScript)"
219 218 ]
220 219 },
221 220 {
222 221 "cell_type": "heading",
223 222 "level": 3,
224 223 "metadata": {},
225 224 "source": [
226 225 "Models and views"
227 226 ]
228 227 },
229 228 {
230 229 "cell_type": "markdown",
231 230 "metadata": {},
232 231 "source": [
233 232 "The IPython widget framework front-end relies heavily on [Backbone.js](http://backbonejs.org/). **Backbone.js is an MVC (model view controller) framework**. Widgets defined in the back-end are automatically **synchronized with generic Backbone.js models** in the front-end. The traitlets are added to the front-end instance **automatically on first state push**. The **`_view_name` trait** that you defined earlier is used by the widget framework to create the corresponding Backbone.js view and **link that view to the model**."
234 233 ]
235 234 },
236 235 {
237 236 "cell_type": "heading",
238 237 "level": 3,
239 238 "metadata": {
240 239 "slideshow": {
241 240 "slide_type": "slide"
242 241 }
243 242 },
244 243 "source": [
245 244 "Import the WidgetManager"
246 245 ]
247 246 },
248 247 {
249 248 "cell_type": "markdown",
250 249 "metadata": {},
251 250 "source": [
252 251 "You first need to **import the `widget` and `manager` modules**. You will use it later to register your view by name (the same name you used in the back-end). To import the modules, use the `require` method of [require.js](http://requirejs.org/) (as seen below)."
253 252 ]
254 253 },
255 254 {
256 255 "cell_type": "code",
257 256 "collapsed": false,
258 257 "input": [
259 258 "%%javascript\n",
260 259 "require([\"widgets/js/widget\", \"widgets/js/manager\"], function(widget, manager){\n",
261 260 " \n",
262 261 "});"
263 262 ],
264 263 "language": "python",
265 264 "metadata": {},
266 265 "outputs": []
267 266 },
268 267 {
269 268 "cell_type": "heading",
270 269 "level": 3,
271 270 "metadata": {
272 271 "slideshow": {
273 272 "slide_type": "slide"
274 273 }
275 274 },
276 275 "source": [
277 276 "Define the view"
278 277 ]
279 278 },
280 279 {
281 280 "cell_type": "markdown",
282 281 "metadata": {},
283 282 "source": [
284 283 "Next define your widget view class. **Inherit from the `DOMWidgetView`** by using the `.extend` method. Register the view class with the widget manager by calling **`.register_widget_view`**. The **first parameter is the widget view name** (`_view_name` that you defined earlier in Python) and the **second is a handle to the class type**."
285 284 ]
286 285 },
287 286 {
288 287 "cell_type": "code",
289 288 "collapsed": false,
290 289 "input": [
291 290 "%%javascript\n",
292 291 "require([\"widgets/js/widget\", \"widgets/js/manager\"], function(widget, manager){\n",
293 292 " \n",
294 293 " // Define the HelloView\n",
295 294 " var HelloView = widget.DOMWidgetView.extend({\n",
296 295 " \n",
297 296 " });\n",
298 297 " \n",
299 298 " // Register the HelloView with the widget manager.\n",
300 299 " manager.WidgetManager.register_widget_view('HelloView', HelloView);\n",
301 300 "});"
302 301 ],
303 302 "language": "python",
304 303 "metadata": {},
305 304 "outputs": []
306 305 },
307 306 {
308 307 "cell_type": "heading",
309 308 "level": 3,
310 309 "metadata": {
311 310 "slideshow": {
312 311 "slide_type": "slide"
313 312 }
314 313 },
315 314 "source": [
316 315 "Render method"
317 316 ]
318 317 },
319 318 {
320 319 "cell_type": "markdown",
321 320 "metadata": {},
322 321 "source": [
323 322 "Lastly, **override the base `render` method** of the view to define custom rendering logic. A handle to the widget's default div element can be acquired via **`this.$el`**. The `$el` property is a **[jQuery](http://jquery.com/) object handle** (which can be thought of as a supercharged version of the normal DOM element's handle)."
324 323 ]
325 324 },
326 325 {
327 326 "cell_type": "code",
328 327 "collapsed": false,
329 328 "input": [
330 329 "%%javascript\n",
331 330 "require([\"widgets/js/widget\", \"widgets/js/manager\"], function(widget, manager){\n",
332 331 " \n",
333 332 " var HelloView = widget.DOMWidgetView.extend({\n",
334 333 " \n",
335 334 " // Render the view.\n",
336 335 " render: function(){ \n",
337 336 " this.$el.text('Hello World!'); \n",
338 337 " },\n",
339 338 " });\n",
340 339 " \n",
341 340 " manager.WidgetManager.register_widget_view('HelloView', HelloView);\n",
342 341 "});"
343 342 ],
344 343 "language": "python",
345 344 "metadata": {},
346 345 "outputs": []
347 346 },
348 347 {
349 348 "cell_type": "heading",
350 349 "level": 2,
351 350 "metadata": {
352 351 "slideshow": {
353 352 "slide_type": "slide"
354 353 }
355 354 },
356 355 "source": [
357 356 "Test"
358 357 ]
359 358 },
360 359 {
361 360 "cell_type": "markdown",
362 361 "metadata": {},
363 362 "source": [
364 363 "You should be able to display your widget just like any other widget now."
365 364 ]
366 365 },
367 366 {
368 367 "cell_type": "code",
369 368 "collapsed": false,
370 369 "input": [
371 370 "HelloWidget()"
372 371 ],
373 372 "language": "python",
374 373 "metadata": {},
375 374 "outputs": []
376 375 },
377 376 {
378 377 "cell_type": "heading",
379 378 "level": 2,
380 379 "metadata": {
381 380 "slideshow": {
382 381 "slide_type": "slide"
383 382 }
384 383 },
385 384 "source": [
386 385 "Making the widget stateful"
387 386 ]
388 387 },
389 388 {
390 389 "cell_type": "markdown",
391 390 "metadata": {},
392 391 "source": [
393 392 "There is not much that you can do with the above example that you can't do with the IPython display framework. To change this, you will make the widget stateful. Instead of displaying a static \"hello world\" message, it will **display a string set by the back-end**. First you need to **add a traitlet in the back-end**. Use the name of **`value` to stay consistent** with the rest of the widget framework and to **allow your widget to be used with interact**."
394 393 ]
395 394 },
396 395 {
397 396 "cell_type": "code",
398 397 "collapsed": false,
399 398 "input": [
400 399 "class HelloWidget(widgets.DOMWidget):\n",
401 400 " _view_name = Unicode('HelloView', sync=True)\n",
402 401 " value = Unicode('Hello World!', sync=True)"
403 402 ],
404 403 "language": "python",
405 404 "metadata": {},
406 405 "outputs": []
407 406 },
408 407 {
409 408 "cell_type": "heading",
410 409 "level": 3,
411 410 "metadata": {
412 411 "slideshow": {
413 412 "slide_type": "slide"
414 413 }
415 414 },
416 415 "source": [
417 416 "Accessing the model from the view"
418 417 ]
419 418 },
420 419 {
421 420 "cell_type": "markdown",
422 421 "metadata": {},
423 422 "source": [
424 423 "To access the model associate with a view instance, use the **`model` property** of the view. **`get` and `set`** methods are used to interact with the Backbone model. **`get` is trivial**, however you have to **be careful when using `set`**. **After calling the model `set`** you need call the **view's `touch` method**. This associates the `set` operation with a particular view so **output will be routed to the correct cell**. The model also has a **`on` method** which allows you to listen to events triggered by the model (like value changes)."
425 424 ]
426 425 },
427 426 {
428 427 "cell_type": "heading",
429 428 "level": 3,
430 429 "metadata": {
431 430 "slideshow": {
432 431 "slide_type": "slide"
433 432 }
434 433 },
435 434 "source": [
436 435 "Rendering model contents"
437 436 ]
438 437 },
439 438 {
440 439 "cell_type": "markdown",
441 440 "metadata": {},
442 441 "source": [
443 442 "By **replacing the string literal with a call to `model.get`**, the view will now display the **value of the back-end upon display**. However, it will not update itself to a new value when the value changes."
444 443 ]
445 444 },
446 445 {
447 446 "cell_type": "code",
448 447 "collapsed": false,
449 448 "input": [
450 449 "%%javascript\n",
451 450 "require([\"widgets/js/widget\", \"widgets/js/manager\"], function(widget, manager){\n",
452 451 " \n",
453 452 " var HelloView = widget.DOMWidgetView.extend({\n",
454 453 " \n",
455 454 " render: function(){ \n",
456 455 " this.$el.text(this.model.get('value')); \n",
457 456 " },\n",
458 457 " });\n",
459 458 " \n",
460 459 " manager.WidgetManager.register_widget_view('HelloView', HelloView);\n",
461 460 "});"
462 461 ],
463 462 "language": "python",
464 463 "metadata": {},
465 464 "outputs": []
466 465 },
467 466 {
468 467 "cell_type": "heading",
469 468 "level": 3,
470 469 "metadata": {
471 470 "slideshow": {
472 471 "slide_type": "slide"
473 472 }
474 473 },
475 474 "source": [
476 475 "Dynamic updates"
477 476 ]
478 477 },
479 478 {
480 479 "cell_type": "markdown",
481 480 "metadata": {},
482 481 "source": [
483 482 "To get the view to **update itself dynamically**, register a function to update the view's value when the model's `value` property changes. This can be done using the **`model.on` method**. The `on` method takes three parameters, an event name, callback handle, and callback context. The Backbone **event named `change`** will fire whenever the model changes. By **appending `:value`** to it, you tell Backbone to only listen to the change event of the `value` property (as seen below)."
484 483 ]
485 484 },
486 485 {
487 486 "cell_type": "code",
488 487 "collapsed": false,
489 488 "input": [
490 489 "%%javascript\n",
491 490 "require([\"widgets/js/widget\", \"widgets/js/manager\"], function(widget, manager){\n",
492 491 " \n",
493 492 " var HelloView = widget.DOMWidgetView.extend({\n",
494 493 " \n",
495 494 " render: function(){ \n",
496 495 " this.value_changed();\n",
497 496 " this.model.on('change:value', this.value_changed, this);\n",
498 497 " },\n",
499 498 " \n",
500 499 " value_changed: function() {\n",
501 500 " this.$el.text(this.model.get('value')); \n",
502 501 " },\n",
503 502 " });\n",
504 503 " \n",
505 504 " manager.WidgetManager.register_widget_view('HelloView', HelloView);\n",
506 505 "});"
507 506 ],
508 507 "language": "python",
509 508 "metadata": {},
510 509 "outputs": []
511 510 },
512 511 {
513 512 "cell_type": "heading",
514 513 "level": 2,
515 514 "metadata": {
516 515 "slideshow": {
517 516 "slide_type": "slide"
518 517 }
519 518 },
520 519 "source": [
521 520 "Test"
522 521 ]
523 522 },
524 523 {
525 524 "cell_type": "code",
526 525 "collapsed": false,
527 526 "input": [
528 527 "w = HelloWidget()\n",
529 528 "w"
530 529 ],
531 530 "language": "python",
532 531 "metadata": {},
533 532 "outputs": []
534 533 },
535 534 {
536 535 "cell_type": "code",
537 536 "collapsed": false,
538 537 "input": [
539 538 "w.value = 'test'"
540 539 ],
541 540 "language": "python",
542 541 "metadata": {},
543 542 "outputs": []
544 543 },
545 544 {
546 545 "cell_type": "heading",
547 546 "level": 1,
548 547 "metadata": {
549 548 "slideshow": {
550 549 "slide_type": "slide"
551 550 }
552 551 },
553 552 "source": [
554 553 "Finishing"
555 554 ]
556 555 },
557 556 {
558 557 "cell_type": "heading",
559 558 "level": 2,
560 559 "metadata": {},
561 560 "source": [
562 561 "Bidirectional communication"
563 562 ]
564 563 },
565 564 {
566 565 "cell_type": "markdown",
567 566 "metadata": {},
568 567 "source": [
569 568 "The examples above dump the value directly into the DOM. There is no way for you to interact with this dumped data in the front-end. To create an example that **accepts input**, you will have to do something more than blindly dumping the contents of value into the DOM. In this part of the tutorial, you will **use a jQuery spinner** to display and accept input in the front-end. IPython currently lacks a spinner implementation so this widget will be unique."
570 569 ]
571 570 },
572 571 {
573 572 "cell_type": "heading",
574 573 "level": 3,
575 574 "metadata": {
576 575 "slideshow": {
577 576 "slide_type": "slide"
578 577 }
579 578 },
580 579 "source": [
581 580 "Update the Python code"
582 581 ]
583 582 },
584 583 {
585 584 "cell_type": "markdown",
586 585 "metadata": {},
587 586 "source": [
588 587 "You will need to change the type of the **value traitlet to `Int`**. It also makes sense to **change the name of the widget** to something more appropriate, like `SpinnerWidget`."
589 588 ]
590 589 },
591 590 {
592 591 "cell_type": "code",
593 592 "collapsed": false,
594 593 "input": [
595 594 "from IPython.utils.traitlets import CInt\n",
596 595 "class SpinnerWidget(widgets.DOMWidget):\n",
597 596 " _view_name = Unicode('SpinnerView', sync=True)\n",
598 597 " value = CInt(0, sync=True)"
599 598 ],
600 599 "language": "python",
601 600 "metadata": {},
602 601 "outputs": []
603 602 },
604 603 {
605 604 "cell_type": "heading",
606 605 "level": 3,
607 606 "metadata": {
608 607 "slideshow": {
609 608 "slide_type": "slide"
610 609 }
611 610 },
612 611 "source": [
613 612 "Updating the Javascript code"
614 613 ]
615 614 },
616 615 {
617 616 "cell_type": "markdown",
618 617 "metadata": {},
619 618 "source": [
620 619 "The [jQuery docs for the spinner control](https://jqueryui.com/spinner/) say to use **`.spinner` to create a spinner** in an element. Calling **`.spinner` on `$el` will create a spinner inside `$el`**. Make sure to **update the widget name here too** so it's the same as `_view_name` in the back-end."
621 620 ]
622 621 },
623 622 {
624 623 "cell_type": "code",
625 624 "collapsed": false,
626 625 "input": [
627 626 "%%javascript\n",
628 627 "require([\"widgets/js/widget\", \"widgets/js/manager\"], function(widget, manager){\n",
629 628 " \n",
630 629 " var SpinnerView = widget.DOMWidgetView.extend({\n",
631 630 " \n",
632 631 " render: function(){ \n",
633 632 " \n",
634 633 " // jQuery code to create a spinner and append it to $el\n",
635 634 " this.$input = $('<input />');\n",
636 635 " this.$el.append(this.$input);\n",
637 636 " this.$spinner = this.$input.spinner({\n",
638 637 " change: function( event, ui ) {}\n",
639 638 " });\n",
640 639 " \n",
641 640 " this.value_changed();\n",
642 641 " this.model.on('change:value', this.value_changed, this);\n",
643 642 " },\n",
644 643 " \n",
645 644 " value_changed: function() {\n",
646 645 " \n",
647 646 " },\n",
648 647 " });\n",
649 648 " \n",
650 649 " manager.WidgetManager.register_widget_view('SpinnerView', SpinnerView);\n",
651 650 "});"
652 651 ],
653 652 "language": "python",
654 653 "metadata": {},
655 654 "outputs": []
656 655 },
657 656 {
658 657 "cell_type": "heading",
659 658 "level": 3,
660 659 "metadata": {
661 660 "slideshow": {
662 661 "slide_type": "slide"
663 662 }
664 663 },
665 664 "source": [
666 665 "Getting and setting the value"
667 666 ]
668 667 },
669 668 {
670 669 "cell_type": "markdown",
671 670 "metadata": {},
672 671 "source": [
673 672 "To **set the value of the spinner on update from the back-end**, you need to use **jQuery's `spinner` API**. `spinner.spinner('value', new)` will set the value of the spinner. Add that code to the **`value_changed` method** to make the spinner **update with the value stored in the back-end((. Using jQuery's spinner API, you can add a function to handle the **spinner `change` event** by passing it in when constructing the spinner. Inside the `change` event, call **`model.set`** to set the value and then **`touch`** to inform the framework that this view was the view that caused the change to the model. **Note: The `var that = this;` is a JavaScript trick to pass the current context into closures.**"
674 673 ]
675 674 },
676 675 {
677 676 "cell_type": "code",
678 677 "collapsed": false,
679 678 "input": [
680 679 "%%javascript\n",
681 680 "require([\"widgets/js/widget\", \"widgets/js/manager\"], function(widget, manager){\n",
682 681 " \n",
683 682 " var SpinnerView = widget.DOMWidgetView.extend({\n",
684 683 " \n",
685 684 " render: function(){ \n",
686 685 "\n",
687 686 " var that = this;\n",
688 687 " this.$input = $('<input />');\n",
689 688 " this.$el.append(this.$input);\n",
690 689 " this.$spinner = this.$input.spinner({\n",
691 690 " change: function( event, ui ) {\n",
692 691 " that.handle_spin();\n",
693 692 " },\n",
694 693 " spin: function( event, ui ) {\n",
695 694 " that.handle_spin();\n",
696 695 " }\n",
697 696 " });\n",
698 697 " \n",
699 698 " this.value_changed();\n",
700 699 " this.model.on('change:value', this.value_changed, this);\n",
701 700 " },\n",
702 701 " \n",
703 702 " value_changed: function() {\n",
704 703 " this.$spinner.spinner('value', this.model.get('value'));\n",
705 704 " },\n",
706 705 " \n",
707 706 " handle_spin: function() {\n",
708 707 " this.model.set('value', this.$spinner.spinner('value'));\n",
709 708 " this.touch();\n",
710 709 " },\n",
711 710 " });\n",
712 711 " \n",
713 712 " manager.WidgetManager.register_widget_view('SpinnerView', SpinnerView);\n",
714 713 "});"
715 714 ],
716 715 "language": "python",
717 716 "metadata": {},
718 717 "outputs": []
719 718 },
720 719 {
721 720 "cell_type": "heading",
722 721 "level": 2,
723 722 "metadata": {
724 723 "slideshow": {
725 724 "slide_type": "slide"
726 725 }
727 726 },
728 727 "source": [
729 728 "Test"
730 729 ]
731 730 },
732 731 {
733 732 "cell_type": "code",
734 733 "collapsed": false,
735 734 "input": [
736 735 "w = SpinnerWidget(value=5)\n",
737 736 "w"
738 737 ],
739 738 "language": "python",
740 739 "metadata": {},
741 740 "outputs": []
742 741 },
743 742 {
744 743 "cell_type": "code",
745 744 "collapsed": false,
746 745 "input": [
747 746 "w.value"
748 747 ],
749 748 "language": "python",
750 749 "metadata": {},
751 750 "outputs": []
752 751 },
753 752 {
754 753 "cell_type": "code",
755 754 "collapsed": false,
756 755 "input": [
757 756 "w.value = 20"
758 757 ],
759 758 "language": "python",
760 759 "metadata": {},
761 760 "outputs": []
762 761 },
763 762 {
764 763 "cell_type": "markdown",
765 764 "metadata": {},
766 765 "source": [
767 766 "Trying to **use the spinner with another widget**."
768 767 ]
769 768 },
770 769 {
771 770 "cell_type": "code",
772 771 "collapsed": false,
773 772 "input": [
774 773 "from IPython.display import display\n",
775 774 "w1 = SpinnerWidget(value=0)\n",
776 775 "w2 = widgets.IntSlider()\n",
777 776 "display(w1,w2)\n",
778 777 "\n",
779 778 "from IPython.utils.traitlets import link\n",
780 779 "mylink = link((w1, 'value'), (w2, 'value'))"
781 780 ],
782 781 "language": "python",
783 782 "metadata": {},
784 783 "outputs": []
785 784 },
786 785 {
787 786 "cell_type": "markdown",
788 787 "metadata": {},
789 788 "source": [
790 789 "[Index](Index.ipynb) - [Back](Widget Styling.ipynb)"
791 790 ]
792 791 }
793 792 ],
794 793 "metadata": {}
795 794 }
796 795 ]
797 796 } No newline at end of file
@@ -1,111 +1,111 b''
1 1 {
2 2 "metadata": {
3 3 "kernelspec": {
4 4 "codemirror_mode": {
5 5 "name": "python",
6 6 "version": 2
7 7 },
8 8 "display_name": "Python 2",
9 9 "language": "python",
10 10 "name": "python2"
11 11 },
12 12 "name": "",
13 "signature": "sha256:cbc67230b7f7d3d8c7ab3a3c5910aaa3e0caf736d0d963892cb2139683caf5fb"
13 "signature": "sha256:8e469f292b096d750dc8eeb71caa8c08b26bc722708314a26a7684c380ccd20f"
14 14 },
15 15 "nbformat": 3,
16 16 "nbformat_minor": 0,
17 17 "worksheets": [
18 18 {
19 19 "cells": [
20 20 {
21 21 "cell_type": "markdown",
22 22 "metadata": {},
23 23 "source": [
24 24 "<img src=\"../images/ipython_logo.png\">"
25 25 ]
26 26 },
27 27 {
28 28 "cell_type": "markdown",
29 29 "metadata": {},
30 30 "source": [
31 31 "Back to the main [Index](../Index.ipynb)"
32 32 ]
33 33 },
34 34 {
35 35 "cell_type": "heading",
36 36 "level": 1,
37 37 "metadata": {},
38 38 "source": [
39 39 "Interactive Widgets"
40 40 ]
41 41 },
42 42 {
43 43 "cell_type": "markdown",
44 44 "metadata": {},
45 45 "source": [
46 46 "IPython includes an architecture for interactive widgets that tie together Python code running in the kernel and JavaScript/HTML/CSS running in the browser. These widgets enable users to explore their code and data interactively."
47 47 ]
48 48 },
49 49 {
50 50 "cell_type": "heading",
51 51 "level": 2,
52 52 "metadata": {},
53 53 "source": [
54 54 "Tutorials"
55 55 ]
56 56 },
57 57 {
58 58 "cell_type": "markdown",
59 59 "metadata": {},
60 60 "source": [
61 61 "- [Using Interact](Using Interact.ipynb)\n",
62 62 "- [Widget Basics](Widget Basics.ipynb) \n",
63 63 "- [Widget Events](Widget Events.ipynb) \n",
64 64 "- [Widget Placement](Widget Placement.ipynb) \n",
65 "- [Widget Styles](Widget Styles.ipynb) \n",
65 "- [Widget Styling](Widget Styling.ipynb) \n",
66 66 "- [Custom Widget](Custom Widget - Hello World.ipynb)"
67 67 ]
68 68 },
69 69 {
70 70 "cell_type": "heading",
71 71 "level": 2,
72 72 "metadata": {},
73 73 "source": [
74 74 "Examples of custom widgets"
75 75 ]
76 76 },
77 77 {
78 78 "cell_type": "markdown",
79 79 "metadata": {},
80 80 "source": [
81 81 "- [Variable Inspector](Variable Inspector.ipynb) \n",
82 82 "- [Export As (nbconvert)](Export As (nbconvert%29.ipynb) \n",
83 83 "- [Nonblocking Console](Nonblocking Console.ipynb) \n",
84 84 "- [File Upload Widget](File Upload Widget.ipynb)"
85 85 ]
86 86 },
87 87 {
88 88 "cell_type": "heading",
89 89 "level": 2,
90 90 "metadata": {},
91 91 "source": [
92 92 "Examples using `interact`/`interactive`"
93 93 ]
94 94 },
95 95 {
96 96 "cell_type": "markdown",
97 97 "metadata": {},
98 98 "source": [
99 99 "* [Beat Frequencies](Beat Frequencies.ipynb)\n",
100 100 "* [Exploring Graphs](Exploring Graphs.ipynb)\n",
101 101 "* [Factoring](Factoring.ipynb)\n",
102 102 "* [Image Browser](Image Browser.ipynb)\n",
103 103 "* [Image Processing](Image Processing.ipynb)\n",
104 104 "* [Lorenz Differential Equations](Lorenz Differential Equations.ipynb)"
105 105 ]
106 106 }
107 107 ],
108 108 "metadata": {}
109 109 }
110 110 ]
111 111 } No newline at end of file
@@ -1,233 +1,233 b''
1 1 {
2 2 "metadata": {
3 3 "kernelspec": {
4 4 "codemirror_mode": {
5 5 "name": "python",
6 6 "version": 2
7 7 },
8 8 "display_name": "Python 2",
9 9 "language": "python",
10 10 "name": "python2"
11 11 },
12 12 "name": "",
13 "signature": "sha256:044aa64f06487b5a08eb26102a46538bfb4e00d37a4cc14edcdf54986a9ef68e"
13 "signature": "sha256:3dfbc0dcb1fefc9ef028022760916b0300e14f71bf8e27589e61800841d5839c"
14 14 },
15 15 "nbformat": 3,
16 16 "nbformat_minor": 0,
17 17 "worksheets": [
18 18 {
19 19 "cells": [
20 20 {
21 21 "cell_type": "code",
22 22 "collapsed": false,
23 23 "input": [
24 24 "# Console related imports.\n",
25 25 "from subprocess import Popen, PIPE\n",
26 26 "import os\n",
27 27 "from IPython.utils.py3compat import bytes_to_str, string_types\n",
28 28 "\n",
29 29 "# Widget related imports.\n",
30 30 "from IPython.html import widgets\n",
31 31 "from IPython.display import display"
32 32 ],
33 33 "language": "python",
34 34 "metadata": {},
35 35 "outputs": []
36 36 },
37 37 {
38 38 "cell_type": "markdown",
39 39 "metadata": {},
40 40 "source": [
41 41 "Define function to run a process without blocking the input."
42 42 ]
43 43 },
44 44 {
45 45 "cell_type": "code",
46 46 "collapsed": false,
47 47 "input": [
48 48 "def read_process(process, append_output):\n",
49 49 " \"\"\" Try to read the stdout and stderr of a process and render it using \n",
50 50 " the append_output method provided\n",
51 51 " \n",
52 52 " Parameters\n",
53 53 " ----------\n",
54 54 " process: Popen handle\n",
55 55 " append_output: method handle\n",
56 56 " Callback to render output. Signature of\n",
57 57 " append_output(output, [prefix=])\"\"\"\n",
58 58 " \n",
59 59 " try:\n",
60 60 " stdout = process.stdout.read()\n",
61 61 " if stdout is not None and len(stdout) > 0:\n",
62 62 " append_output(stdout, prefix=' ')\n",
63 63 " except:\n",
64 64 " pass\n",
65 65 " \n",
66 66 " try:\n",
67 67 " stderr = process.stderr.read()\n",
68 68 " if stderr is not None and len(stderr) > 0:\n",
69 69 " append_output(stderr, prefix='ERR ')\n",
70 70 " except:\n",
71 71 " pass\n",
72 72 "\n",
73 73 "\n",
74 74 "def set_pipe_nonblocking(pipe):\n",
75 75 " \"\"\"Set a pipe as non-blocking\"\"\"\n",
76 76 " try:\n",
77 77 " import fcntl\n",
78 78 " fl = fcntl.fcntl(pipe, fcntl.F_GETFL)\n",
79 79 " fcntl.fcntl(pipe, fcntl.F_SETFL, fl | os.O_NONBLOCK)\n",
80 80 " except:\n",
81 81 " pass\n",
82 82 "\n",
83 83 "kernel = get_ipython().kernel\n",
84 84 "def run_command(command, append_output, has_user_exited=None):\n",
85 85 " \"\"\"Run a command asyncronously\n",
86 86 " \n",
87 87 " Parameters\n",
88 88 " ----------\n",
89 89 " command: str\n",
90 90 " Shell command to launch a process with.\n",
91 91 " append_output: method handle\n",
92 92 " Callback to render output. Signature of\n",
93 93 " append_output(output, [prefix=])\n",
94 94 " has_user_exited: method handle\n",
95 95 " Check to see if the user wants to stop the command.\n",
96 96 " Must return a boolean.\"\"\"\n",
97 97 " \n",
98 98 " # Echo input.\n",
99 99 " append_output(command, prefix='>>> ')\n",
100 100 " \n",
101 101 " # Create the process. Make sure the pipes are set as non-blocking.\n",
102 102 " process = Popen(command, shell=True, stdout=PIPE, stderr=PIPE)\n",
103 103 " set_pipe_nonblocking(process.stdout)\n",
104 104 " set_pipe_nonblocking(process.stderr)\n",
105 105 " \n",
106 106 " # Only continue to read from the command \n",
107 107 " while (has_user_exited is None or not has_user_exited()) and process.poll() is None:\n",
108 108 " read_process(process, append_output)\n",
109 109 " kernel.do_one_iteration() # Run IPython iteration. This is the code that\n",
110 110 " # makes this operation non-blocking. This will\n",
111 111 " # allow widget messages and callbacks to be \n",
112 112 " # processed.\n",
113 113 " \n",
114 114 " # If the process is still running, the user must have exited.\n",
115 115 " if process.poll() is None:\n",
116 116 " process.kill()\n",
117 117 " else:\n",
118 118 " read_process(process, append_output) # Read remainer\n",
119 119 " \n",
120 120 " \n",
121 121 " \n",
122 122 " "
123 123 ],
124 124 "language": "python",
125 125 "metadata": {},
126 126 "outputs": []
127 127 },
128 128 {
129 129 "cell_type": "markdown",
130 130 "metadata": {},
131 131 "source": [
132 132 "Create the console widgets without displaying them."
133 133 ]
134 134 },
135 135 {
136 136 "cell_type": "code",
137 137 "collapsed": false,
138 138 "input": [
139 139 "console_container = widgets.VBox(visible=False)\n",
140 140 "console_container.padding = '10px'\n",
141 141 "\n",
142 142 "output_box = widgets.Textarea()\n",
143 143 "output_box.height = '400px'\n",
144 144 "output_box.font_family = 'monospace'\n",
145 "output_box.fore_color = '#AAAAAA'\n",
146 "output_box.back_color = 'black'\n",
145 "output_box.color = '#AAAAAA'\n",
146 "output_box.background_color = 'black'\n",
147 147 "output_box.width = '800px'\n",
148 148 "\n",
149 149 "input_box = widgets.Text()\n",
150 150 "input_box.font_family = 'monospace'\n",
151 "input_box.fore_color = '#AAAAAA'\n",
152 "input_box.back_color = 'black'\n",
151 "input_box.color = '#AAAAAA'\n",
152 "input_box.background_color = 'black'\n",
153 153 "input_box.width = '800px'\n",
154 154 "\n",
155 155 "console_container.children = [output_box, input_box]"
156 156 ],
157 157 "language": "python",
158 158 "metadata": {},
159 159 "outputs": []
160 160 },
161 161 {
162 162 "cell_type": "markdown",
163 163 "metadata": {},
164 164 "source": [
165 165 "Hook the process execution methods up to our console widgets."
166 166 ]
167 167 },
168 168 {
169 169 "cell_type": "code",
170 170 "collapsed": false,
171 171 "input": [
172 172 "\n",
173 173 "def append_output(output, prefix):\n",
174 174 " if isinstance(output, string_types):\n",
175 175 " output_str = output\n",
176 176 " else:\n",
177 177 " output_str = bytes_to_str(output)\n",
178 178 " output_lines = output_str.split('\\n')\n",
179 179 " formatted_output = '\\n'.join([prefix + line for line in output_lines if len(line) > 0]) + '\\n'\n",
180 180 " output_box.value += formatted_output\n",
181 181 " output_box.scroll_to_bottom()\n",
182 182 " \n",
183 183 "def has_user_exited():\n",
184 184 " return not console_container.visible\n",
185 185 "\n",
186 186 "def handle_input(sender):\n",
187 187 " sender.disabled = True\n",
188 188 " try:\n",
189 189 " command = sender.value\n",
190 190 " sender.value = ''\n",
191 191 " run_command(command, append_output=append_output, has_user_exited=has_user_exited)\n",
192 192 " finally:\n",
193 193 " sender.disabled = False\n",
194 194 " \n",
195 195 "input_box.on_submit(handle_input)"
196 196 ],
197 197 "language": "python",
198 198 "metadata": {},
199 199 "outputs": []
200 200 },
201 201 {
202 202 "cell_type": "markdown",
203 203 "metadata": {},
204 204 "source": [
205 205 "Create the button that will be used to display and hide the console. Display both the console container and the new button used to toggle it."
206 206 ]
207 207 },
208 208 {
209 209 "cell_type": "code",
210 210 "collapsed": false,
211 211 "input": [
212 212 "toggle_button = widgets.Button(description=\"Start Console\")\n",
213 213 "def toggle_console(sender):\n",
214 214 " console_container.visible = not console_container.visible\n",
215 215 " if console_container.visible:\n",
216 216 " toggle_button.description=\"Stop Console\"\n",
217 217 " input_box.disabled = False\n",
218 218 " else:\n",
219 219 " toggle_button.description=\"Start Console\"\n",
220 220 "toggle_button.on_click(toggle_console)\n",
221 221 "\n",
222 222 "display(toggle_button)\n",
223 223 "display(console_container)"
224 224 ],
225 225 "language": "python",
226 226 "metadata": {},
227 227 "outputs": []
228 228 }
229 229 ],
230 230 "metadata": {}
231 231 }
232 232 ]
233 233 } No newline at end of file
@@ -1,446 +1,445 b''
1 1 {
2 2 "metadata": {
3 "celltoolbar": "Slideshow",
4 3 "kernelspec": {
5 4 "codemirror_mode": {
6 5 "name": "python",
7 6 "version": 2
8 7 },
9 8 "display_name": "Python 2",
10 9 "language": "python",
11 10 "name": "python2"
12 11 },
13 12 "name": "",
14 "signature": "sha256:942aa1b77fbab2ba0fa5e52a6e30fe1231a07e5f2a9ef9fc495e106a08e65e39"
13 "signature": "sha256:c8af7f5d30b29ee52fe6a79cf0d573c9c2d5b2f522b04731249e3208671741d3"
15 14 },
16 15 "nbformat": 3,
17 16 "nbformat_minor": 0,
18 17 "worksheets": [
19 18 {
20 19 "cells": [
21 20 {
22 21 "cell_type": "markdown",
23 22 "metadata": {},
24 23 "source": [
25 24 "[Index](Index.ipynb) - [Next](Widget List.ipynb)"
26 25 ]
27 26 },
28 27 {
29 28 "cell_type": "heading",
30 29 "level": 1,
31 30 "metadata": {},
32 31 "source": [
33 32 "Simple Widget Introduction"
34 33 ]
35 34 },
36 35 {
37 36 "cell_type": "heading",
38 37 "level": 2,
39 38 "metadata": {},
40 39 "source": [
41 40 "What are widgets?"
42 41 ]
43 42 },
44 43 {
45 44 "cell_type": "markdown",
46 45 "metadata": {
47 46 "slideshow": {
48 47 "slide_type": "slide"
49 48 }
50 49 },
51 50 "source": [
52 51 "Widgets are elements that exists in both the front-end and the back-end.\n",
53 52 "\n",
54 53 "![Kernel & front-end diagram](../images/FrontendKernel.png)"
55 54 ]
56 55 },
57 56 {
58 57 "cell_type": "heading",
59 58 "level": 2,
60 59 "metadata": {},
61 60 "source": [
62 61 "What can they be used for?"
63 62 ]
64 63 },
65 64 {
66 65 "cell_type": "markdown",
67 66 "metadata": {
68 67 "slideshow": {
69 68 "slide_type": "slide"
70 69 }
71 70 },
72 71 "source": [
73 72 "You can use widgets to build **interactive GUIs** for your notebooks. \n",
74 73 "You can also use widgets to **synchronize stateful and stateless information** between Python and JavaScript."
75 74 ]
76 75 },
77 76 {
78 77 "cell_type": "heading",
79 78 "level": 2,
80 79 "metadata": {},
81 80 "source": [
82 81 "Using widgets "
83 82 ]
84 83 },
85 84 {
86 85 "cell_type": "markdown",
87 86 "metadata": {
88 87 "slideshow": {
89 88 "slide_type": "slide"
90 89 }
91 90 },
92 91 "source": [
93 92 "To use the widget framework, you need to **import `IPython.html.widgets`**."
94 93 ]
95 94 },
96 95 {
97 96 "cell_type": "code",
98 97 "collapsed": false,
99 98 "input": [
100 99 "from IPython.html.widgets import *"
101 100 ],
102 101 "language": "python",
103 102 "metadata": {},
104 103 "outputs": []
105 104 },
106 105 {
107 106 "cell_type": "heading",
108 107 "level": 3,
109 108 "metadata": {
110 109 "slideshow": {
111 110 "slide_type": "slide"
112 111 }
113 112 },
114 113 "source": [
115 114 "repr"
116 115 ]
117 116 },
118 117 {
119 118 "cell_type": "markdown",
120 119 "metadata": {},
121 120 "source": [
122 121 "Widgets have their own display `repr` which allows them to be displayed using IPython's display framework. Constructing and returning an `IntSlider` automatically displays the widget (as seen below). Widgets are **displayed inside the `widget area`**, which sits between the code cell and output. **You can hide all of the widgets** in the `widget area` by clicking the grey *x* in the margin."
123 122 ]
124 123 },
125 124 {
126 125 "cell_type": "code",
127 126 "collapsed": false,
128 127 "input": [
129 128 "IntSlider()"
130 129 ],
131 130 "language": "python",
132 131 "metadata": {},
133 132 "outputs": []
134 133 },
135 134 {
136 135 "cell_type": "heading",
137 136 "level": 3,
138 137 "metadata": {
139 138 "slideshow": {
140 139 "slide_type": "slide"
141 140 }
142 141 },
143 142 "source": [
144 143 "display()"
145 144 ]
146 145 },
147 146 {
148 147 "cell_type": "markdown",
149 148 "metadata": {},
150 149 "source": [
151 150 "You can also explicitly display the widget using `display(...)`."
152 151 ]
153 152 },
154 153 {
155 154 "cell_type": "code",
156 155 "collapsed": false,
157 156 "input": [
158 157 "from IPython.display import display\n",
159 158 "w = IntSlider()\n",
160 159 "display(w)"
161 160 ],
162 161 "language": "python",
163 162 "metadata": {},
164 163 "outputs": []
165 164 },
166 165 {
167 166 "cell_type": "heading",
168 167 "level": 3,
169 168 "metadata": {
170 169 "slideshow": {
171 170 "slide_type": "slide"
172 171 }
173 172 },
174 173 "source": [
175 174 "Multiple display() calls"
176 175 ]
177 176 },
178 177 {
179 178 "cell_type": "markdown",
180 179 "metadata": {},
181 180 "source": [
182 181 "If you display the same widget twice, the displayed instances in the front-end **will remain in sync** with each other."
183 182 ]
184 183 },
185 184 {
186 185 "cell_type": "code",
187 186 "collapsed": false,
188 187 "input": [
189 188 "display(w)"
190 189 ],
191 190 "language": "python",
192 191 "metadata": {},
193 192 "outputs": []
194 193 },
195 194 {
196 195 "cell_type": "heading",
197 196 "level": 2,
198 197 "metadata": {},
199 198 "source": [
200 199 "Why does displaying the same widget twice work?"
201 200 ]
202 201 },
203 202 {
204 203 "cell_type": "markdown",
205 204 "metadata": {
206 205 "slideshow": {
207 206 "slide_type": "slide"
208 207 }
209 208 },
210 209 "source": [
211 210 "Widgets are **represented in the back-end by a single object**. Each time a widget is displayed, **a new representation** of that same object is created in the front-end. These representations are called **views**.\n",
212 211 "\n",
213 212 "![Kernel & front-end diagram](images/WidgetModelView.png)"
214 213 ]
215 214 },
216 215 {
217 216 "cell_type": "heading",
218 217 "level": 3,
219 218 "metadata": {
220 219 "slideshow": {
221 220 "slide_type": "slide"
222 221 }
223 222 },
224 223 "source": [
225 224 "Closing widgets"
226 225 ]
227 226 },
228 227 {
229 228 "cell_type": "markdown",
230 229 "metadata": {},
231 230 "source": [
232 231 "You can close a widget by calling its `close()` method."
233 232 ]
234 233 },
235 234 {
236 235 "cell_type": "code",
237 236 "collapsed": false,
238 237 "input": [
239 238 "display(w)"
240 239 ],
241 240 "language": "python",
242 241 "metadata": {},
243 242 "outputs": []
244 243 },
245 244 {
246 245 "cell_type": "code",
247 246 "collapsed": false,
248 247 "input": [
249 248 "w.close()"
250 249 ],
251 250 "language": "python",
252 251 "metadata": {},
253 252 "outputs": []
254 253 },
255 254 {
256 255 "cell_type": "heading",
257 256 "level": 2,
258 257 "metadata": {},
259 258 "source": [
260 259 "Widget properties"
261 260 ]
262 261 },
263 262 {
264 263 "cell_type": "markdown",
265 264 "metadata": {
266 265 "slideshow": {
267 266 "slide_type": "slide"
268 267 }
269 268 },
270 269 "source": [
271 270 "All of the IPython widgets **share a similar naming scheme**. To read the value of a widget, you can query its `value` property."
272 271 ]
273 272 },
274 273 {
275 274 "cell_type": "code",
276 275 "collapsed": false,
277 276 "input": [
278 277 "w = IntSlider()\n",
279 278 "display(w)"
280 279 ],
281 280 "language": "python",
282 281 "metadata": {},
283 282 "outputs": []
284 283 },
285 284 {
286 285 "cell_type": "code",
287 286 "collapsed": false,
288 287 "input": [
289 288 "w.value"
290 289 ],
291 290 "language": "python",
292 291 "metadata": {},
293 292 "outputs": []
294 293 },
295 294 {
296 295 "cell_type": "markdown",
297 296 "metadata": {},
298 297 "source": [
299 298 "Similarly, to set a widget's value, you can set its `value` property."
300 299 ]
301 300 },
302 301 {
303 302 "cell_type": "code",
304 303 "collapsed": false,
305 304 "input": [
306 305 "w.value = 100"
307 306 ],
308 307 "language": "python",
309 308 "metadata": {},
310 309 "outputs": []
311 310 },
312 311 {
313 312 "cell_type": "heading",
314 313 "level": 3,
315 314 "metadata": {
316 315 "slideshow": {
317 316 "slide_type": "slide"
318 317 }
319 318 },
320 319 "source": [
321 320 "Keys"
322 321 ]
323 322 },
324 323 {
325 324 "cell_type": "markdown",
326 325 "metadata": {},
327 326 "source": [
328 327 "In addition to `value`, most widgets share `keys`, `description`, `disabled`, and `visible`. To see the entire list of synchronized, stateful properties, of any specific widget, you can **query the `keys` property**."
329 328 ]
330 329 },
331 330 {
332 331 "cell_type": "code",
333 332 "collapsed": false,
334 333 "input": [
335 334 "w.keys"
336 335 ],
337 336 "language": "python",
338 337 "metadata": {},
339 338 "outputs": []
340 339 },
341 340 {
342 341 "cell_type": "heading",
343 342 "level": 3,
344 343 "metadata": {},
345 344 "source": [
346 345 "Shorthand for setting the initial values of widget properties"
347 346 ]
348 347 },
349 348 {
350 349 "cell_type": "markdown",
351 350 "metadata": {
352 351 "slideshow": {
353 352 "slide_type": "slide"
354 353 }
355 354 },
356 355 "source": [
357 356 "While creating a widget, you can set some or all of the initial values of that widget by **defining them as keyword arguments in the widget's constructor** (as seen below)."
358 357 ]
359 358 },
360 359 {
361 360 "cell_type": "code",
362 361 "collapsed": false,
363 362 "input": [
364 363 "Text(value='Hello World!', disabled=True)"
365 364 ],
366 365 "language": "python",
367 366 "metadata": {},
368 367 "outputs": []
369 368 },
370 369 {
371 370 "cell_type": "heading",
372 371 "level": 2,
373 372 "metadata": {},
374 373 "source": [
375 374 "Linking two similar widgets"
376 375 ]
377 376 },
378 377 {
379 378 "cell_type": "markdown",
380 379 "metadata": {
381 380 "slideshow": {
382 381 "slide_type": "slide"
383 382 }
384 383 },
385 384 "source": [
386 385 "If you need to display the same value two different ways, you'll have to use two different widgets. Instead of **attempting to manually synchronize the values** of the two widgets, you can use the `traitlet` `link` function **to link two properties together**. Below, the values of three widgets are linked together."
387 386 ]
388 387 },
389 388 {
390 389 "cell_type": "code",
391 390 "collapsed": false,
392 391 "input": [
393 392 "from IPython.utils.traitlets import link\n",
394 393 "a = FloatText()\n",
395 394 "b = FloatSlider()\n",
396 395 "c = FloatProgress()\n",
397 396 "display(a,b,c)\n",
398 397 "\n",
399 398 "\n",
400 399 "mylink = link((a, 'value'), (b, 'value'), (c, 'value'))"
401 400 ],
402 401 "language": "python",
403 402 "metadata": {},
404 403 "outputs": []
405 404 },
406 405 {
407 406 "cell_type": "heading",
408 407 "level": 3,
409 408 "metadata": {},
410 409 "source": [
411 410 "Unlinking widgets"
412 411 ]
413 412 },
414 413 {
415 414 "cell_type": "markdown",
416 415 "metadata": {
417 416 "slideshow": {
418 417 "slide_type": "slide"
419 418 }
420 419 },
421 420 "source": [
422 421 "Unlinking the widgets is simple. All you have to do is call `.unlink` on the link object."
423 422 ]
424 423 },
425 424 {
426 425 "cell_type": "code",
427 426 "collapsed": false,
428 427 "input": [
429 428 "mylink.unlink()"
430 429 ],
431 430 "language": "python",
432 431 "metadata": {},
433 432 "outputs": []
434 433 },
435 434 {
436 435 "cell_type": "markdown",
437 436 "metadata": {},
438 437 "source": [
439 438 "[Index](Index.ipynb) - [Next](Widget List.ipynb)"
440 439 ]
441 440 }
442 441 ],
443 442 "metadata": {}
444 443 }
445 444 ]
446 445 } No newline at end of file
@@ -1,235 +1,234 b''
1 1 {
2 2 "metadata": {
3 3 "cell_tags": [
4 4 [
5 5 "<None>",
6 6 null
7 7 ]
8 8 ],
9 "celltoolbar": "Slideshow",
10 9 "kernelspec": {
11 10 "codemirror_mode": {
12 11 "name": "python",
13 12 "version": 2
14 13 },
15 14 "display_name": "Python 2",
16 15 "language": "python",
17 16 "name": "python2"
18 17 },
19 18 "name": "",
20 "signature": "sha256:0e46490eebb11503b7a7411065535d6fbc5ebcf61a519f0b030281f303086bdc"
19 "signature": "sha256:05a3e92089b37f68e3134587ffef6ef73830e5f8b3c515ba24640d7c803820c3"
21 20 },
22 21 "nbformat": 3,
23 22 "nbformat_minor": 0,
24 23 "worksheets": [
25 24 {
26 25 "cells": [
27 26 {
28 27 "cell_type": "markdown",
29 28 "metadata": {},
30 29 "source": [
31 30 "[Index](Index.ipynb) - [Back](Widget List.ipynb) - [Next](Widget Styling.ipynb)"
32 31 ]
33 32 },
34 33 {
35 34 "cell_type": "heading",
36 35 "level": 1,
37 36 "metadata": {
38 37 "slideshow": {
39 38 "slide_type": "slide"
40 39 }
41 40 },
42 41 "source": [
43 42 "Widget Events"
44 43 ]
45 44 },
46 45 {
47 46 "cell_type": "heading",
48 47 "level": 2,
49 48 "metadata": {},
50 49 "source": [
51 50 "Special events"
52 51 ]
53 52 },
54 53 {
55 54 "cell_type": "code",
56 55 "collapsed": false,
57 56 "input": [
58 57 "from __future__ import print_function"
59 58 ],
60 59 "language": "python",
61 60 "metadata": {},
62 61 "outputs": []
63 62 },
64 63 {
65 64 "cell_type": "markdown",
66 65 "metadata": {},
67 66 "source": [
68 67 "The `Button` is not used to represent a data type. Instead the button widget is used to **handle mouse clicks**. The **`on_click` method** of the `Button` can be used to register function to be called when the button is clicked. The doc string of the `on_click` can be seen below."
69 68 ]
70 69 },
71 70 {
72 71 "cell_type": "code",
73 72 "collapsed": false,
74 73 "input": [
75 74 "from IPython.html import widgets\n",
76 75 "print(widgets.Button.on_click.__doc__)"
77 76 ],
78 77 "language": "python",
79 78 "metadata": {},
80 79 "outputs": []
81 80 },
82 81 {
83 82 "cell_type": "heading",
84 83 "level": 3,
85 84 "metadata": {
86 85 "slideshow": {
87 86 "slide_type": "slide"
88 87 }
89 88 },
90 89 "source": [
91 90 "Example"
92 91 ]
93 92 },
94 93 {
95 94 "cell_type": "markdown",
96 95 "metadata": {},
97 96 "source": [
98 97 "Since button clicks are **stateless**, they are **transmitted from the front-end to the back-end using custom messages**. By using the `on_click` method, a button that prints a message when it has been clicked is shown below."
99 98 ]
100 99 },
101 100 {
102 101 "cell_type": "code",
103 102 "collapsed": false,
104 103 "input": [
105 104 "from IPython.display import display\n",
106 105 "button = widgets.Button(description=\"Click Me!\")\n",
107 106 "display(button)\n",
108 107 "\n",
109 108 "def on_button_clicked(b):\n",
110 109 " print(\"Button clicked.\")\n",
111 110 "\n",
112 111 "button.on_click(on_button_clicked)"
113 112 ],
114 113 "language": "python",
115 114 "metadata": {},
116 115 "outputs": []
117 116 },
118 117 {
119 118 "cell_type": "heading",
120 119 "level": 3,
121 120 "metadata": {
122 121 "slideshow": {
123 122 "slide_type": "slide"
124 123 }
125 124 },
126 125 "source": [
127 126 "on_sumbit"
128 127 ]
129 128 },
130 129 {
131 130 "cell_type": "markdown",
132 131 "metadata": {},
133 132 "source": [
134 133 "The **`Text`** also has a special **`on_submit` event**. The `on_submit` event **fires when the user hits return**."
135 134 ]
136 135 },
137 136 {
138 137 "cell_type": "code",
139 138 "collapsed": false,
140 139 "input": [
141 140 "text = widgets.Text()\n",
142 141 "display(text)\n",
143 142 "\n",
144 143 "def handle_submit(sender):\n",
145 144 " print(text.value)\n",
146 145 "\n",
147 146 "text.on_submit(handle_submit)"
148 147 ],
149 148 "language": "python",
150 149 "metadata": {},
151 150 "outputs": []
152 151 },
153 152 {
154 153 "cell_type": "heading",
155 154 "level": 2,
156 155 "metadata": {
157 156 "slideshow": {
158 157 "slide_type": "slide"
159 158 }
160 159 },
161 160 "source": [
162 161 "Traitlet events"
163 162 ]
164 163 },
165 164 {
166 165 "cell_type": "markdown",
167 166 "metadata": {},
168 167 "source": [
169 168 "**Widget properties are IPython traitlets** and **traitlets are eventful**. To handle changes, the **`on_trait_change` method** of the widget can be used to **register a callback**. The doc string for `on_trait_change` can be seen below."
170 169 ]
171 170 },
172 171 {
173 172 "cell_type": "code",
174 173 "collapsed": false,
175 174 "input": [
176 175 "print(widgets.Widget.on_trait_change.__doc__)"
177 176 ],
178 177 "language": "python",
179 178 "metadata": {},
180 179 "outputs": []
181 180 },
182 181 {
183 182 "cell_type": "heading",
184 183 "level": 3,
185 184 "metadata": {
186 185 "slideshow": {
187 186 "slide_type": "slide"
188 187 }
189 188 },
190 189 "source": [
191 190 "Signatures"
192 191 ]
193 192 },
194 193 {
195 194 "cell_type": "markdown",
196 195 "metadata": {},
197 196 "source": [
198 197 "Mentioned in the doc string, the callback registered can have **4 possible signatures**:\n",
199 198 "\n",
200 199 "- callback()\n",
201 200 "- callback(trait_name)\n",
202 201 "- callback(trait_name, new_value)\n",
203 202 "- callback(trait_name, old_value, new_value)\n",
204 203 "\n",
205 204 "Using this method, an example of how to output an `IntSlider`'s value as it is changed can be seen below."
206 205 ]
207 206 },
208 207 {
209 208 "cell_type": "code",
210 209 "collapsed": false,
211 210 "input": [
212 211 "int_range = widgets.IntSlider()\n",
213 212 "display(int_range)\n",
214 213 "\n",
215 214 "def on_value_change(name, value):\n",
216 215 " print(value)\n",
217 216 "\n",
218 217 "int_range.on_trait_change(on_value_change, 'value')"
219 218 ],
220 219 "language": "python",
221 220 "metadata": {},
222 221 "outputs": []
223 222 },
224 223 {
225 224 "cell_type": "markdown",
226 225 "metadata": {},
227 226 "source": [
228 227 "[Index](Index.ipynb) - [Back](Widget List.ipynb) - [Next](Widget Styling.ipynb)"
229 228 ]
230 229 }
231 230 ],
232 231 "metadata": {}
233 232 }
234 233 ]
235 234 } No newline at end of file
@@ -1,588 +1,587 b''
1 1 {
2 2 "metadata": {
3 "celltoolbar": "Slideshow",
4 3 "kernelspec": {
5 4 "codemirror_mode": {
6 5 "name": "python",
7 6 "version": 2
8 7 },
9 8 "display_name": "Python 2",
10 9 "language": "python",
11 10 "name": "python2"
12 11 },
13 12 "name": "",
14 "signature": "sha256:869807fa658843bb4742bab3bab7ce4d164a0e3285e3bf840ad76ede2e252b79"
13 "signature": "sha256:83b39d018a7a6ae0a324b9f3d38debafbfb2ed0a114e4bbd357fb318f8f23438"
15 14 },
16 15 "nbformat": 3,
17 16 "nbformat_minor": 0,
18 17 "worksheets": [
19 18 {
20 19 "cells": [
21 20 {
22 21 "cell_type": "markdown",
23 22 "metadata": {},
24 23 "source": [
25 24 "[Index](Index.ipynb) - [Back](Widget Basics.ipynb) - [Next](Widget Events.ipynb)"
26 25 ]
27 26 },
28 27 {
29 28 "cell_type": "heading",
30 29 "level": 1,
31 30 "metadata": {},
32 31 "source": [
33 32 "Widget List"
34 33 ]
35 34 },
36 35 {
37 36 "cell_type": "heading",
38 37 "level": 2,
39 38 "metadata": {},
40 39 "source": [
41 40 "Complete list"
42 41 ]
43 42 },
44 43 {
45 44 "cell_type": "markdown",
46 45 "metadata": {
47 46 "slideshow": {
48 47 "slide_type": "slide"
49 48 }
50 49 },
51 50 "source": [
52 51 "For a complete list of the widgets available to you, you can list the classes in the widget namespace (as seen below). `Widget` and `DOMWidget`, not listed below, are base classes."
53 52 ]
54 53 },
55 54 {
56 55 "cell_type": "code",
57 56 "collapsed": false,
58 57 "input": [
59 58 "from IPython.html import widgets\n",
60 59 "[n for n in dir(widgets) if not n.endswith('Widget') and n[0] == n[0].upper() and not n[0] == '_']"
61 60 ],
62 61 "language": "python",
63 62 "metadata": {},
64 63 "outputs": []
65 64 },
66 65 {
67 66 "cell_type": "heading",
68 67 "level": 2,
69 68 "metadata": {
70 69 "slideshow": {
71 70 "slide_type": "slide"
72 71 }
73 72 },
74 73 "source": [
75 74 "Numeric widgets"
76 75 ]
77 76 },
78 77 {
79 78 "cell_type": "markdown",
80 79 "metadata": {},
81 80 "source": [
82 81 "There are 8 widgets distributed with IPython that are designed to display numeric values. Widgets exist for displaying integers and floats, both bounded and unbounded. The integer widgets share a similar naming scheme to their floating point counterparts. By replacing `Float` with `Int` in the widget name, you can find the Integer equivalent."
83 82 ]
84 83 },
85 84 {
86 85 "cell_type": "heading",
87 86 "level": 3,
88 87 "metadata": {
89 88 "slideshow": {
90 89 "slide_type": "slide"
91 90 }
92 91 },
93 92 "source": [
94 93 "FloatSlider"
95 94 ]
96 95 },
97 96 {
98 97 "cell_type": "code",
99 98 "collapsed": false,
100 99 "input": [
101 100 "widgets.FloatSlider(\n",
102 101 " value=7.5,\n",
103 102 " min=5.0,\n",
104 103 " max=10.0,\n",
105 104 " step=0.1,\n",
106 105 " description='Test:',\n",
107 106 ")"
108 107 ],
109 108 "language": "python",
110 109 "metadata": {},
111 110 "outputs": []
112 111 },
113 112 {
114 113 "cell_type": "markdown",
115 114 "metadata": {},
116 115 "source": [
117 116 "Sliders can also be **displayed vertically**."
118 117 ]
119 118 },
120 119 {
121 120 "cell_type": "code",
122 121 "collapsed": false,
123 122 "input": [
124 123 "widgets.FloatSlider(\n",
125 124 " value=7.5,\n",
126 125 " min=5.0,\n",
127 126 " max=10.0,\n",
128 127 " step=0.1,\n",
129 128 " description='Test',\n",
130 129 " orientation='vertical',\n",
131 130 ")"
132 131 ],
133 132 "language": "python",
134 133 "metadata": {},
135 134 "outputs": []
136 135 },
137 136 {
138 137 "cell_type": "heading",
139 138 "level": 3,
140 139 "metadata": {
141 140 "slideshow": {
142 141 "slide_type": "slide"
143 142 }
144 143 },
145 144 "source": [
146 145 "FloatProgress"
147 146 ]
148 147 },
149 148 {
150 149 "cell_type": "code",
151 150 "collapsed": false,
152 151 "input": [
153 152 "widgets.FloatProgress(\n",
154 153 " value=7.5,\n",
155 154 " min=5.0,\n",
156 155 " max=10.0,\n",
157 156 " step=0.1,\n",
158 157 " description='Loading:',\n",
159 158 ")"
160 159 ],
161 160 "language": "python",
162 161 "metadata": {},
163 162 "outputs": []
164 163 },
165 164 {
166 165 "cell_type": "heading",
167 166 "level": 3,
168 167 "metadata": {
169 168 "slideshow": {
170 169 "slide_type": "slide"
171 170 }
172 171 },
173 172 "source": [
174 173 "BoundedFloatText"
175 174 ]
176 175 },
177 176 {
178 177 "cell_type": "code",
179 178 "collapsed": false,
180 179 "input": [
181 180 "widgets.BoundedFloatText(\n",
182 181 " value=7.5,\n",
183 182 " min=5.0,\n",
184 183 " max=10.0,\n",
185 184 " description='Text:',\n",
186 185 ")"
187 186 ],
188 187 "language": "python",
189 188 "metadata": {},
190 189 "outputs": []
191 190 },
192 191 {
193 192 "cell_type": "heading",
194 193 "level": 3,
195 194 "metadata": {
196 195 "slideshow": {
197 196 "slide_type": "slide"
198 197 }
199 198 },
200 199 "source": [
201 200 "FloatText"
202 201 ]
203 202 },
204 203 {
205 204 "cell_type": "code",
206 205 "collapsed": false,
207 206 "input": [
208 207 "widgets.FloatText(\n",
209 208 " value=7.5,\n",
210 209 " description='Any:',\n",
211 210 ")"
212 211 ],
213 212 "language": "python",
214 213 "metadata": {},
215 214 "outputs": []
216 215 },
217 216 {
218 217 "cell_type": "heading",
219 218 "level": 2,
220 219 "metadata": {
221 220 "slideshow": {
222 221 "slide_type": "slide"
223 222 }
224 223 },
225 224 "source": [
226 225 "Boolean widgets"
227 226 ]
228 227 },
229 228 {
230 229 "cell_type": "markdown",
231 230 "metadata": {},
232 231 "source": [
233 232 "There are two widgets that are designed to display a boolean value."
234 233 ]
235 234 },
236 235 {
237 236 "cell_type": "heading",
238 237 "level": 3,
239 238 "metadata": {},
240 239 "source": [
241 240 "ToggleButton"
242 241 ]
243 242 },
244 243 {
245 244 "cell_type": "code",
246 245 "collapsed": false,
247 246 "input": [
248 247 "widgets.ToggleButton(\n",
249 248 " description='Click me',\n",
250 249 " value=False,\n",
251 250 ")"
252 251 ],
253 252 "language": "python",
254 253 "metadata": {},
255 254 "outputs": []
256 255 },
257 256 {
258 257 "cell_type": "heading",
259 258 "level": 3,
260 259 "metadata": {
261 260 "slideshow": {
262 261 "slide_type": "slide"
263 262 }
264 263 },
265 264 "source": [
266 265 "Checkbox"
267 266 ]
268 267 },
269 268 {
270 269 "cell_type": "code",
271 270 "collapsed": false,
272 271 "input": [
273 272 "widgets.Checkbox(\n",
274 273 " description='Check me',\n",
275 274 " value=True,\n",
276 275 ")"
277 276 ],
278 277 "language": "python",
279 278 "metadata": {},
280 279 "outputs": []
281 280 },
282 281 {
283 282 "cell_type": "heading",
284 283 "level": 2,
285 284 "metadata": {
286 285 "slideshow": {
287 286 "slide_type": "slide"
288 287 }
289 288 },
290 289 "source": [
291 290 "Selection widgets"
292 291 ]
293 292 },
294 293 {
295 294 "cell_type": "markdown",
296 295 "metadata": {},
297 296 "source": [
298 297 "There are four widgets that can be used to display single selection lists. All four inherit from the same base class. You can specify the **enumeration of selectables by passing a list**. You can **also specify the enumeration as a dictionary**, in which case the **keys will be used as the item displayed** in the list and the corresponding **value will be returned** when an item is selected."
299 298 ]
300 299 },
301 300 {
302 301 "cell_type": "heading",
303 302 "level": 3,
304 303 "metadata": {
305 304 "slideshow": {
306 305 "slide_type": "slide"
307 306 }
308 307 },
309 308 "source": [
310 309 "Dropdown"
311 310 ]
312 311 },
313 312 {
314 313 "cell_type": "code",
315 314 "collapsed": false,
316 315 "input": [
317 316 "from IPython.display import display\n",
318 317 "w = widgets.Dropdown(\n",
319 318 " values=[1, 2, 3],\n",
320 319 " value=2,\n",
321 320 " description='Number:',\n",
322 321 ")\n",
323 322 "display(w)"
324 323 ],
325 324 "language": "python",
326 325 "metadata": {},
327 326 "outputs": []
328 327 },
329 328 {
330 329 "cell_type": "code",
331 330 "collapsed": false,
332 331 "input": [
333 332 "w.value"
334 333 ],
335 334 "language": "python",
336 335 "metadata": {},
337 336 "outputs": []
338 337 },
339 338 {
340 339 "cell_type": "markdown",
341 340 "metadata": {},
342 341 "source": [
343 342 "The following is also valid:"
344 343 ]
345 344 },
346 345 {
347 346 "cell_type": "code",
348 347 "collapsed": false,
349 348 "input": [
350 349 "w = widgets.Dropdown(\n",
351 350 " values={'One': 1, 'Two': 2, 'Three': 3},\n",
352 351 " value=2,\n",
353 352 " description='Number:',\n",
354 353 ")\n",
355 354 "display(w)"
356 355 ],
357 356 "language": "python",
358 357 "metadata": {},
359 358 "outputs": []
360 359 },
361 360 {
362 361 "cell_type": "code",
363 362 "collapsed": false,
364 363 "input": [
365 364 "w.value"
366 365 ],
367 366 "language": "python",
368 367 "metadata": {},
369 368 "outputs": []
370 369 },
371 370 {
372 371 "cell_type": "heading",
373 372 "level": 3,
374 373 "metadata": {
375 374 "slideshow": {
376 375 "slide_type": "slide"
377 376 }
378 377 },
379 378 "source": [
380 379 "RadioButtons"
381 380 ]
382 381 },
383 382 {
384 383 "cell_type": "code",
385 384 "collapsed": false,
386 385 "input": [
387 386 "widgets.RadioButtons(\n",
388 387 " description='Pizza topping:',\n",
389 388 " values=['pepperoni', 'pineapple', 'anchovies'],\n",
390 389 ")"
391 390 ],
392 391 "language": "python",
393 392 "metadata": {},
394 393 "outputs": []
395 394 },
396 395 {
397 396 "cell_type": "heading",
398 397 "level": 3,
399 398 "metadata": {
400 399 "slideshow": {
401 400 "slide_type": "slide"
402 401 }
403 402 },
404 403 "source": [
405 404 "Select"
406 405 ]
407 406 },
408 407 {
409 408 "cell_type": "code",
410 409 "collapsed": false,
411 410 "input": [
412 411 "widgets.Select(\n",
413 412 " description='OS:',\n",
414 413 " values=['Linux', 'Windows', 'OSX'],\n",
415 414 ")"
416 415 ],
417 416 "language": "python",
418 417 "metadata": {},
419 418 "outputs": []
420 419 },
421 420 {
422 421 "cell_type": "heading",
423 422 "level": 3,
424 423 "metadata": {
425 424 "slideshow": {
426 425 "slide_type": "slide"
427 426 }
428 427 },
429 428 "source": [
430 429 "ToggleButtons"
431 430 ]
432 431 },
433 432 {
434 433 "cell_type": "code",
435 434 "collapsed": false,
436 435 "input": [
437 436 "widgets.ToggleButtons(\n",
438 437 " description='Speed:',\n",
439 438 " values=['Slow', 'Regular', 'Fast'],\n",
440 439 ")"
441 440 ],
442 441 "language": "python",
443 442 "metadata": {},
444 443 "outputs": []
445 444 },
446 445 {
447 446 "cell_type": "heading",
448 447 "level": 2,
449 448 "metadata": {
450 449 "slideshow": {
451 450 "slide_type": "slide"
452 451 }
453 452 },
454 453 "source": [
455 454 "String widgets"
456 455 ]
457 456 },
458 457 {
459 458 "cell_type": "markdown",
460 459 "metadata": {},
461 460 "source": [
462 461 "There are 4 widgets that can be used to display a string value. Of those, the **`Text` and `Textarea` widgets accept input**. The **`Latex` and `HTML` widgets display the string** as either Latex or HTML respectively, but **do not accept input**."
463 462 ]
464 463 },
465 464 {
466 465 "cell_type": "heading",
467 466 "level": 3,
468 467 "metadata": {
469 468 "slideshow": {
470 469 "slide_type": "slide"
471 470 }
472 471 },
473 472 "source": [
474 473 "Text"
475 474 ]
476 475 },
477 476 {
478 477 "cell_type": "code",
479 478 "collapsed": false,
480 479 "input": [
481 480 "widgets.Text(\n",
482 481 " description='String:',\n",
483 482 " value='Hello World',\n",
484 483 ")"
485 484 ],
486 485 "language": "python",
487 486 "metadata": {},
488 487 "outputs": []
489 488 },
490 489 {
491 490 "cell_type": "heading",
492 491 "level": 3,
493 492 "metadata": {},
494 493 "source": [
495 494 "Textarea"
496 495 ]
497 496 },
498 497 {
499 498 "cell_type": "code",
500 499 "collapsed": false,
501 500 "input": [
502 501 "widgets.Textarea(\n",
503 502 " description='String:',\n",
504 503 " value='Hello World',\n",
505 504 ")"
506 505 ],
507 506 "language": "python",
508 507 "metadata": {},
509 508 "outputs": []
510 509 },
511 510 {
512 511 "cell_type": "heading",
513 512 "level": 3,
514 513 "metadata": {
515 514 "slideshow": {
516 515 "slide_type": "slide"
517 516 }
518 517 },
519 518 "source": [
520 519 "Latex"
521 520 ]
522 521 },
523 522 {
524 523 "cell_type": "code",
525 524 "collapsed": false,
526 525 "input": [
527 526 "widgets.Latex(\n",
528 527 " value=\"$$\\\\frac{n!}{k!(n-k)!} = \\\\binom{n}{k}$$\",\n",
529 528 ")"
530 529 ],
531 530 "language": "python",
532 531 "metadata": {},
533 532 "outputs": []
534 533 },
535 534 {
536 535 "cell_type": "heading",
537 536 "level": 3,
538 537 "metadata": {},
539 538 "source": [
540 539 "HTML"
541 540 ]
542 541 },
543 542 {
544 543 "cell_type": "code",
545 544 "collapsed": false,
546 545 "input": [
547 546 "widgets.HTML(\n",
548 547 " value=\"Hello <b>World</b>\"\n",
549 548 ")"
550 549 ],
551 550 "language": "python",
552 551 "metadata": {},
553 552 "outputs": []
554 553 },
555 554 {
556 555 "cell_type": "heading",
557 556 "level": 2,
558 557 "metadata": {
559 558 "slideshow": {
560 559 "slide_type": "slide"
561 560 }
562 561 },
563 562 "source": [
564 563 "Button"
565 564 ]
566 565 },
567 566 {
568 567 "cell_type": "code",
569 568 "collapsed": false,
570 569 "input": [
571 570 "widgets.Button(description='Click me')"
572 571 ],
573 572 "language": "python",
574 573 "metadata": {},
575 574 "outputs": []
576 575 },
577 576 {
578 577 "cell_type": "markdown",
579 578 "metadata": {},
580 579 "source": [
581 580 "[Index](Index.ipynb) - [Back](Widget Basics.ipynb) - [Next](Widget Events.ipynb)"
582 581 ]
583 582 }
584 583 ],
585 584 "metadata": {}
586 585 }
587 586 ]
588 587 } No newline at end of file
@@ -1,738 +1,737 b''
1 1 {
2 2 "metadata": {
3 3 "cell_tags": [
4 4 [
5 5 "<None>",
6 6 null
7 7 ]
8 8 ],
9 "celltoolbar": "Slideshow",
10 9 "kernelspec": {
11 10 "codemirror_mode": {
12 11 "name": "python",
13 12 "version": 2
14 13 },
15 14 "display_name": "Python 2",
16 15 "language": "python",
17 16 "name": "python2"
18 17 },
19 18 "name": "",
20 "signature": "sha256:f6e8d46c3edeaf2371bf508730c093f8d1005cc9be13072aabf71dc3f49b2c3b"
19 "signature": "sha256:8bb091be85fd5e7f76082b1b4b98cddec92a856334935ac2c702fe5ec03f6eff"
21 20 },
22 21 "nbformat": 3,
23 22 "nbformat_minor": 0,
24 23 "worksheets": [
25 24 {
26 25 "cells": [
27 26 {
28 27 "cell_type": "markdown",
29 28 "metadata": {},
30 29 "source": [
31 30 "[Index](Index.ipynb) - [Back](Widget Events.ipynb) - [Next](Custom Widget - Hello World.ipynb)"
32 31 ]
33 32 },
34 33 {
35 34 "cell_type": "code",
36 35 "collapsed": false,
37 36 "input": [
38 37 "%%html\n",
39 38 "<style>\n",
40 39 ".example-container { background: #999999; padding: 2px; min-height: 100px; }\n",
41 40 ".example-container.sm { min-height: 50px; }\n",
42 41 ".example-box { background: #9999FF; width: 50px; height: 50px; text-align: center; vertical-align: middle; color: white; font-weight: bold; margin: 2px;}\n",
43 42 ".example-box.med { width: 65px; height: 65px; } \n",
44 43 ".example-box.lrg { width: 80px; height: 80px; } \n",
45 44 "</style>"
46 45 ],
47 46 "language": "python",
48 47 "metadata": {},
49 48 "outputs": []
50 49 },
51 50 {
52 51 "cell_type": "code",
53 52 "collapsed": false,
54 53 "input": [
55 54 "from IPython.html import widgets\n",
56 55 "from IPython.display import display"
57 56 ],
58 57 "language": "python",
59 58 "metadata": {},
60 59 "outputs": []
61 60 },
62 61 {
63 62 "cell_type": "heading",
64 63 "level": 1,
65 64 "metadata": {
66 65 "slideshow": {
67 66 "slide_type": "slide"
68 67 }
69 68 },
70 69 "source": [
71 70 "Widget Styling"
72 71 ]
73 72 },
74 73 {
75 74 "cell_type": "heading",
76 75 "level": 2,
77 76 "metadata": {},
78 77 "source": [
79 78 "Basic styling"
80 79 ]
81 80 },
82 81 {
83 82 "cell_type": "markdown",
84 83 "metadata": {},
85 84 "source": [
86 85 "The widgets distributed with IPython can be styled by setting the following traits:\n",
87 86 "\n",
88 87 "- width \n",
89 88 "- height \n",
90 89 "- fore_color \n",
91 90 "- back_color \n",
92 91 "- border_color \n",
93 92 "- border_width \n",
94 93 "- border_style \n",
95 94 "- font_style \n",
96 95 "- font_weight \n",
97 96 "- font_size \n",
98 97 "- font_family \n",
99 98 "\n",
100 99 "The example below shows how a `Button` widget can be styled:"
101 100 ]
102 101 },
103 102 {
104 103 "cell_type": "code",
105 104 "collapsed": false,
106 105 "input": [
107 106 "button = widgets.Button(\n",
108 107 " description='Hello World!',\n",
109 108 " width=100, # Integers are interpreted as pixel measurements.\n",
110 109 " height='2em', # em is valid HTML unit of measurement.\n",
111 " fore_color='lime', # Colors can be set by name,\n",
112 " back_color='#0022FF', # and also by color code.\n",
110 " color='lime', # Colors can be set by name,\n",
111 " background_color='#0022FF', # and also by color code.\n",
113 112 " border_color='red')\n",
114 113 "display(button)"
115 114 ],
116 115 "language": "python",
117 116 "metadata": {},
118 117 "outputs": []
119 118 },
120 119 {
121 120 "cell_type": "heading",
122 121 "level": 2,
123 122 "metadata": {
124 123 "slideshow": {
125 124 "slide_type": "slide"
126 125 }
127 126 },
128 127 "source": [
129 128 "Parent/child relationships"
130 129 ]
131 130 },
132 131 {
133 132 "cell_type": "markdown",
134 133 "metadata": {},
135 134 "source": [
136 135 "To display widget A inside widget B, widget A must be a child of widget B. Widgets that can contain other widgets have a **`children` attribute**. This attribute can be **set via a keyword argument** in the widget's constructor **or after construction**. Calling display on an **object with children automatically displays those children**, too."
137 136 ]
138 137 },
139 138 {
140 139 "cell_type": "code",
141 140 "collapsed": false,
142 141 "input": [
143 142 "from IPython.display import display\n",
144 143 "\n",
145 144 "float_range = widgets.FloatSlider()\n",
146 145 "string = widgets.Text(value='hi')\n",
147 146 "container = widgets.Box(children=[float_range, string])\n",
148 147 "\n",
149 148 "container.border_color = 'red'\n",
150 149 "container.border_style = 'dotted'\n",
151 150 "container.border_width = 3\n",
152 151 "display(container) # Displays the `container` and all of it's children."
153 152 ],
154 153 "language": "python",
155 154 "metadata": {},
156 155 "outputs": []
157 156 },
158 157 {
159 158 "cell_type": "heading",
160 159 "level": 3,
161 160 "metadata": {},
162 161 "source": [
163 162 "After the parent is displayed"
164 163 ]
165 164 },
166 165 {
167 166 "cell_type": "markdown",
168 167 "metadata": {
169 168 "slideshow": {
170 169 "slide_type": "slide"
171 170 }
172 171 },
173 172 "source": [
174 173 "Children **can be added to parents** after the parent has been displayed. The **parent is responsible for rendering its children**."
175 174 ]
176 175 },
177 176 {
178 177 "cell_type": "code",
179 178 "collapsed": false,
180 179 "input": [
181 180 "container = widgets.Box()\n",
182 181 "container.border_color = 'red'\n",
183 182 "container.border_style = 'dotted'\n",
184 183 "container.border_width = 3\n",
185 184 "display(container)\n",
186 185 "\n",
187 186 "int_range = widgets.IntSlider()\n",
188 187 "container.children=[int_range]"
189 188 ],
190 189 "language": "python",
191 190 "metadata": {},
192 191 "outputs": []
193 192 },
194 193 {
195 194 "cell_type": "heading",
196 195 "level": 2,
197 196 "metadata": {
198 197 "slideshow": {
199 198 "slide_type": "slide"
200 199 }
201 200 },
202 201 "source": [
203 202 "Fancy boxes"
204 203 ]
205 204 },
206 205 {
207 206 "cell_type": "markdown",
208 207 "metadata": {},
209 208 "source": [
210 209 "If you need to display a more complicated set of widgets, there are **specialized containers** that you can use. To display **multiple sets of widgets**, you can use an **`Accordion` or a `Tab` in combination with one `Box` per set of widgets** (as seen below). The \"pages\" of these widgets are their children. To set the titles of the pages, one must **call `set_title` after the widget has been displayed**."
211 210 ]
212 211 },
213 212 {
214 213 "cell_type": "heading",
215 214 "level": 3,
216 215 "metadata": {},
217 216 "source": [
218 217 "Accordion"
219 218 ]
220 219 },
221 220 {
222 221 "cell_type": "code",
223 222 "collapsed": false,
224 223 "input": [
225 224 "name1 = widgets.Text(description='Location:')\n",
226 225 "zip1 = widgets.BoundedIntText(description='Zip:', min=0, max=99999)\n",
227 226 "page1 = widgets.Box(children=[name1, zip1])\n",
228 227 "\n",
229 228 "name2 = widgets.Text(description='Location:')\n",
230 229 "zip2 = widgets.BoundedIntText(description='Zip:', min=0, max=99999)\n",
231 230 "page2 = widgets.Box(children=[name2, zip2])\n",
232 231 "\n",
233 232 "accord = widgets.Accordion(children=[page1, page2])\n",
234 233 "display(accord)\n",
235 234 "\n",
236 235 "accord.set_title(0, 'From')\n",
237 236 "accord.set_title(1, 'To')"
238 237 ],
239 238 "language": "python",
240 239 "metadata": {},
241 240 "outputs": []
242 241 },
243 242 {
244 243 "cell_type": "heading",
245 244 "level": 3,
246 245 "metadata": {
247 246 "slideshow": {
248 247 "slide_type": "slide"
249 248 }
250 249 },
251 250 "source": [
252 251 "TabWidget"
253 252 ]
254 253 },
255 254 {
256 255 "cell_type": "code",
257 256 "collapsed": false,
258 257 "input": [
259 258 "name = widgets.Text(description='Name:')\n",
260 259 "color = widgets.Dropdown(description='Color:', values=['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet'])\n",
261 260 "page1 = widgets.Box(children=[name, color])\n",
262 261 "\n",
263 262 "age = widgets.IntSlider(description='Age:', min=0, max=120, value=50)\n",
264 263 "gender = widgets.RadioButtons(description='Gender:', values=['male', 'female'])\n",
265 264 "page2 = widgets.Box(children=[age, gender])\n",
266 265 "\n",
267 266 "tabs = widgets.Tab(children=[page1, page2])\n",
268 267 "display(tabs)\n",
269 268 "\n",
270 269 "tabs.set_title(0, 'Name')\n",
271 270 "tabs.set_title(1, 'Details')"
272 271 ],
273 272 "language": "python",
274 273 "metadata": {},
275 274 "outputs": []
276 275 },
277 276 {
278 277 "cell_type": "heading",
279 278 "level": 3,
280 279 "metadata": {
281 280 "slideshow": {
282 281 "slide_type": "slide"
283 282 }
284 283 },
285 284 "source": [
286 285 "Popup"
287 286 ]
288 287 },
289 288 {
290 289 "cell_type": "markdown",
291 290 "metadata": {},
292 291 "source": [
293 292 "Unlike the other two special containers, the `Popup` is only **designed to display one set of widgets**. The `Popup` can be used to **display widgets outside of the widget area**. "
294 293 ]
295 294 },
296 295 {
297 296 "cell_type": "code",
298 297 "collapsed": false,
299 298 "input": [
300 299 "counter = widgets.IntText(description='Counter:')\n",
301 300 "popup = widgets.Popup(children=[counter], description='Popup Demo', button_text='Popup Button')\n",
302 301 "display(popup)"
303 302 ],
304 303 "language": "python",
305 304 "metadata": {},
306 305 "outputs": []
307 306 },
308 307 {
309 308 "cell_type": "code",
310 309 "collapsed": false,
311 310 "input": [
312 311 "counter.value += 1"
313 312 ],
314 313 "language": "python",
315 314 "metadata": {},
316 315 "outputs": []
317 316 },
318 317 {
319 318 "cell_type": "code",
320 319 "collapsed": false,
321 320 "input": [],
322 321 "language": "python",
323 322 "metadata": {},
324 323 "outputs": []
325 324 },
326 325 {
327 326 "cell_type": "code",
328 327 "collapsed": false,
329 328 "input": [],
330 329 "language": "python",
331 330 "metadata": {},
332 331 "outputs": []
333 332 },
334 333 {
335 334 "cell_type": "code",
336 335 "collapsed": false,
337 336 "input": [],
338 337 "language": "python",
339 338 "metadata": {},
340 339 "outputs": []
341 340 },
342 341 {
343 342 "cell_type": "code",
344 343 "collapsed": false,
345 344 "input": [],
346 345 "language": "python",
347 346 "metadata": {},
348 347 "outputs": []
349 348 },
350 349 {
351 350 "cell_type": "code",
352 351 "collapsed": false,
353 352 "input": [],
354 353 "language": "python",
355 354 "metadata": {},
356 355 "outputs": []
357 356 },
358 357 {
359 358 "cell_type": "code",
360 359 "collapsed": false,
361 360 "input": [],
362 361 "language": "python",
363 362 "metadata": {},
364 363 "outputs": []
365 364 },
366 365 {
367 366 "cell_type": "code",
368 367 "collapsed": false,
369 368 "input": [],
370 369 "language": "python",
371 370 "metadata": {},
372 371 "outputs": []
373 372 },
374 373 {
375 374 "cell_type": "code",
376 375 "collapsed": false,
377 376 "input": [],
378 377 "language": "python",
379 378 "metadata": {},
380 379 "outputs": []
381 380 },
382 381 {
383 382 "cell_type": "code",
384 383 "collapsed": false,
385 384 "input": [],
386 385 "language": "python",
387 386 "metadata": {},
388 387 "outputs": []
389 388 },
390 389 {
391 390 "cell_type": "code",
392 391 "collapsed": false,
393 392 "input": [],
394 393 "language": "python",
395 394 "metadata": {},
396 395 "outputs": []
397 396 },
398 397 {
399 398 "cell_type": "code",
400 399 "collapsed": false,
401 400 "input": [],
402 401 "language": "python",
403 402 "metadata": {},
404 403 "outputs": []
405 404 },
406 405 {
407 406 "cell_type": "code",
408 407 "collapsed": false,
409 408 "input": [],
410 409 "language": "python",
411 410 "metadata": {},
412 411 "outputs": []
413 412 },
414 413 {
415 414 "cell_type": "code",
416 415 "collapsed": false,
417 416 "input": [],
418 417 "language": "python",
419 418 "metadata": {},
420 419 "outputs": []
421 420 },
422 421 {
423 422 "cell_type": "code",
424 423 "collapsed": false,
425 424 "input": [],
426 425 "language": "python",
427 426 "metadata": {},
428 427 "outputs": []
429 428 },
430 429 {
431 430 "cell_type": "code",
432 431 "collapsed": false,
433 432 "input": [
434 433 "counter.value += 1"
435 434 ],
436 435 "language": "python",
437 436 "metadata": {},
438 437 "outputs": []
439 438 },
440 439 {
441 440 "cell_type": "code",
442 441 "collapsed": false,
443 442 "input": [
444 443 "popup.close()"
445 444 ],
446 445 "language": "python",
447 446 "metadata": {},
448 447 "outputs": []
449 448 },
450 449 {
451 450 "cell_type": "heading",
452 451 "level": 1,
453 452 "metadata": {
454 453 "slideshow": {
455 454 "slide_type": "slide"
456 455 }
457 456 },
458 457 "source": [
459 458 "Alignment"
460 459 ]
461 460 },
462 461 {
463 462 "cell_type": "markdown",
464 463 "metadata": {},
465 464 "source": [
466 465 "Most widgets have a **`description` attribute**, which allows a label for the widget to be defined.\n",
467 466 "The label of the widget **has a fixed minimum width**.\n",
468 467 "The text of the label is **always right aligned and the widget is left aligned**:"
469 468 ]
470 469 },
471 470 {
472 471 "cell_type": "code",
473 472 "collapsed": false,
474 473 "input": [
475 474 "display(widgets.Text(description=\"a:\"))\n",
476 475 "display(widgets.Text(description=\"aa:\"))\n",
477 476 "display(widgets.Text(description=\"aaa:\"))"
478 477 ],
479 478 "language": "python",
480 479 "metadata": {},
481 480 "outputs": []
482 481 },
483 482 {
484 483 "cell_type": "markdown",
485 484 "metadata": {
486 485 "slideshow": {
487 486 "slide_type": "slide"
488 487 }
489 488 },
490 489 "source": [
491 490 "If a **label is longer** than the minimum width, the **widget is shifted to the right**:"
492 491 ]
493 492 },
494 493 {
495 494 "cell_type": "code",
496 495 "collapsed": false,
497 496 "input": [
498 497 "display(widgets.Text(description=\"a:\"))\n",
499 498 "display(widgets.Text(description=\"aa:\"))\n",
500 499 "display(widgets.Text(description=\"aaa:\"))\n",
501 500 "display(widgets.Text(description=\"aaaaaaaaaaaaaaaaaa:\"))"
502 501 ],
503 502 "language": "python",
504 503 "metadata": {},
505 504 "outputs": []
506 505 },
507 506 {
508 507 "cell_type": "markdown",
509 508 "metadata": {
510 509 "slideshow": {
511 510 "slide_type": "slide"
512 511 }
513 512 },
514 513 "source": [
515 514 "If a `description` is **not set** for the widget, the **label is not displayed**:"
516 515 ]
517 516 },
518 517 {
519 518 "cell_type": "code",
520 519 "collapsed": false,
521 520 "input": [
522 521 "display(widgets.Text(description=\"a:\"))\n",
523 522 "display(widgets.Text(description=\"aa:\"))\n",
524 523 "display(widgets.Text(description=\"aaa:\"))\n",
525 524 "display(widgets.Text())"
526 525 ],
527 526 "language": "python",
528 527 "metadata": {},
529 528 "outputs": []
530 529 },
531 530 {
532 531 "cell_type": "heading",
533 532 "level": 2,
534 533 "metadata": {
535 534 "slideshow": {
536 535 "slide_type": "slide"
537 536 }
538 537 },
539 538 "source": [
540 539 "Flex boxes"
541 540 ]
542 541 },
543 542 {
544 543 "cell_type": "markdown",
545 544 "metadata": {},
546 545 "source": [
547 546 "Widgets can be aligned using the `FlexBox`, `HBox`, and `VBox` widgets."
548 547 ]
549 548 },
550 549 {
551 550 "cell_type": "heading",
552 551 "level": 3,
553 552 "metadata": {
554 553 "slideshow": {
555 554 "slide_type": "slide"
556 555 }
557 556 },
558 557 "source": [
559 558 "Application to widgets"
560 559 ]
561 560 },
562 561 {
563 562 "cell_type": "markdown",
564 563 "metadata": {},
565 564 "source": [
566 565 "Widgets display vertically by default:"
567 566 ]
568 567 },
569 568 {
570 569 "cell_type": "code",
571 570 "collapsed": false,
572 571 "input": [
573 572 "buttons = [widgets.Button(description=str(i)) for i in range(3)]\n",
574 573 "display(*buttons)"
575 574 ],
576 575 "language": "python",
577 576 "metadata": {},
578 577 "outputs": []
579 578 },
580 579 {
581 580 "cell_type": "heading",
582 581 "level": 3,
583 582 "metadata": {
584 583 "slideshow": {
585 584 "slide_type": "slide"
586 585 }
587 586 },
588 587 "source": [
589 588 "Using hbox"
590 589 ]
591 590 },
592 591 {
593 592 "cell_type": "markdown",
594 593 "metadata": {},
595 594 "source": [
596 595 "To make widgets display horizontally, you need to **child them to a `HBox` widget**."
597 596 ]
598 597 },
599 598 {
600 599 "cell_type": "code",
601 600 "collapsed": false,
602 601 "input": [
603 602 "container = widgets.HBox(children=buttons)\n",
604 603 "display(container)"
605 604 ],
606 605 "language": "python",
607 606 "metadata": {},
608 607 "outputs": []
609 608 },
610 609 {
611 610 "cell_type": "markdown",
612 611 "metadata": {},
613 612 "source": [
614 613 "By setting the width of the container to 100% and its `pack` to `center`, you can center the buttons."
615 614 ]
616 615 },
617 616 {
618 617 "cell_type": "code",
619 618 "collapsed": false,
620 619 "input": [
621 620 "container.width = '100%'\n",
622 621 "container.pack = 'center'"
623 622 ],
624 623 "language": "python",
625 624 "metadata": {},
626 625 "outputs": []
627 626 },
628 627 {
629 628 "cell_type": "heading",
630 629 "level": 2,
631 630 "metadata": {
632 631 "slideshow": {
633 632 "slide_type": "slide"
634 633 }
635 634 },
636 635 "source": [
637 636 "Visibility"
638 637 ]
639 638 },
640 639 {
641 640 "cell_type": "markdown",
642 641 "metadata": {},
643 642 "source": [
644 643 "Sometimes it is necessary to **hide or show widgets** in place, **without having to re-display** the widget.\n",
645 644 "The `visibility` property of widgets can be used to hide or show **widgets that have already been displayed** (as seen below)."
646 645 ]
647 646 },
648 647 {
649 648 "cell_type": "code",
650 649 "collapsed": false,
651 650 "input": [
652 651 "string = widgets.Latex(value=\"Hello World!\")\n",
653 652 "display(string) "
654 653 ],
655 654 "language": "python",
656 655 "metadata": {},
657 656 "outputs": []
658 657 },
659 658 {
660 659 "cell_type": "code",
661 660 "collapsed": false,
662 661 "input": [
663 662 "string.visible=False"
664 663 ],
665 664 "language": "python",
666 665 "metadata": {},
667 666 "outputs": []
668 667 },
669 668 {
670 669 "cell_type": "code",
671 670 "collapsed": false,
672 671 "input": [
673 672 "string.visible=True"
674 673 ],
675 674 "language": "python",
676 675 "metadata": {},
677 676 "outputs": []
678 677 },
679 678 {
680 679 "cell_type": "heading",
681 680 "level": 3,
682 681 "metadata": {
683 682 "slideshow": {
684 683 "slide_type": "slide"
685 684 }
686 685 },
687 686 "source": [
688 687 "Another example"
689 688 ]
690 689 },
691 690 {
692 691 "cell_type": "markdown",
693 692 "metadata": {},
694 693 "source": [
695 694 "In the example below, a form is rendered, which conditionally displays widgets depending on the state of other widgets. Try toggling the student checkbox."
696 695 ]
697 696 },
698 697 {
699 698 "cell_type": "code",
700 699 "collapsed": false,
701 700 "input": [
702 701 "form = widgets.VBox()\n",
703 702 "first = widgets.Text(description=\"First Name:\")\n",
704 703 "last = widgets.Text(description=\"Last Name:\")\n",
705 704 "\n",
706 705 "student = widgets.Checkbox(description=\"Student:\", value=False)\n",
707 706 "school_info = widgets.VBox(visible=False, children=[\n",
708 707 " widgets.Text(description=\"School:\"),\n",
709 708 " widgets.IntText(description=\"Grade:\", min=0, max=12)\n",
710 709 " ])\n",
711 710 "\n",
712 711 "pet = widgets.Text(description=\"Pet's Name:\")\n",
713 712 "form.children = [first, last, student, school_info, pet]\n",
714 713 "display(form)\n",
715 714 "\n",
716 715 "def on_student_toggle(name, value):\n",
717 716 " if value:\n",
718 717 " school_info.visible = True\n",
719 718 " else:\n",
720 719 " school_info.visible = False\n",
721 720 "student.on_trait_change(on_student_toggle, 'value')\n"
722 721 ],
723 722 "language": "python",
724 723 "metadata": {},
725 724 "outputs": []
726 725 },
727 726 {
728 727 "cell_type": "markdown",
729 728 "metadata": {},
730 729 "source": [
731 730 "[Index](Index.ipynb) - [Back](Widget Events.ipynb) - [Next](Custom Widget - Hello World.ipynb)"
732 731 ]
733 732 }
734 733 ],
735 734 "metadata": {}
736 735 }
737 736 ]
738 737 } No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now