#!/usr/bin/env python # coding: utf-8 # # 07 [補充] Jupyter 裡的 Widgets # # 有很多同學問到, 我們用 `ipywidgets` 的 `interact` 或 `interact_manual` 可以做得更漂亮、更客制化我們想要的功能嗎? # # 答案是肯定的。 # # 這就要用到眾多很酷的 widgets。雖然每次設定麻煩一點點, 但不管是種類還是自由度都高很多。 # ## 1. Widgets 概念 # # 我們先來引入一個 `widget`, 然後大概介紹這有可能可以做什麼。 # In[1]: from ipywidgets.widgets import * from IPython.display import display # 這裡要注意, 有個 `widget` 叫 `HTML`, 但這和之前我們引入的 # # ```python # from IPython.display import HTML # ``` # # 是不同的! # In[2]: html = HTML('

Hi

') # In[3]: display(html) # 這目前看來一樣? 不一樣是我們可以 display 很多次, 而且你可以之後修改顯示內容。 # In[4]: display(html) # In[5]: html.value = '

你好

' # 你會發現, 兩次的 display 都改了!! 這有什麼好處呢? 這就是我們放上一個在網頁上的 widget, 我們可以去改變它呈現的樣子。 # # 為了示範一個「小動畫」例子, 我們做一隻會跑的蟲。為了不要讓蟲蟲「瞬間移動」, 我們引入 `sleep`。 # In[6]: from time import sleep # In[7]: worm = HTML('
oooo
') # In[8]: display(worm) for i in range(80): htmlbase = '
%s
' html = htmlbase % (" " * (i+1) + "oooo") worm.value = html sleep(0.2) # 這裡說明一下, 我們用到的 # #   # # 是 HTML 的空白。直接打空白你會發現 HTML 不理你, 當然你也可以直接打「全型的空白」, 因為 HTML 基本上當成一個文字, 所以會乖乖顯示。 # # 而 # # sleep(0.2) # # 是說讓 Python 「睡」 0.2 秒, 再繼繼下一個動作。 # #### [練習] 讓蟲蟲爬回來 # # 有同學問到, 可以自動讓蟲蟲爬回來可以嗎? 當然可以啊, 試試看吧 :) # ## 2. 進度條 # # 進度條就是像我們下載大型檔案時, 電腦會出現目前已進行多少百分比的進度那個指示條。你可以看到反正每次要使用一個 widget, 就是先宣告一個 widget, 然後用 `display` 顯示出來。再來就是可以改一些裡面的設定, 最常改的就是 `value`。 # In[9]: p = IntProgress() # In[10]: display(p) # 這空空的進度條當然沒什麼好看的, 我們可以設任一個 0 到 100 的數字給它, 比如說: # In[11]: p.value=55 # 當然會動的進度表更有感覺 :) # # 為了看清楚, 我們再一次顯示同一個進度表, 注意和之前的進度表是完全連動的! # In[12]: display(p) for i in range(101): p.value = i sleep(0.1) # ## 3. 老朋友, 數值滑桿 # # 我們回來看看之前用 `interact` 就會出現的數值滑桿。我們為何要自已呼叫呢? 因為更可以完全客制化, 更彈性的運用。 # In[13]: s = IntSlider(min=1, max=10) s.style.handle_color="#44AF69" #s.style.background_color="#1FDE91" #s.color="#44AF69" #s.slider_color="#FCAB10" #s.background_color="#1FDE91" # In[14]: display(s) # 倒底有什麼參數可以改呢? 我們可以列出來看看。 # In[15]: s.keys # 而且, 我們還可以客制化的精美數值滑桿用到之前的 `interact` 中。 # In[16]: from ipywidgets import interact # In[17]: def f(x): print(x) # In[18]: interact(f, x=s); # ## 4. 應該有個叫按鈕的東西 # # 互動介面中, 我們常常用到的按鈕, 應該有個吧? 那是當然的。按鈕和之前的應用有點不一樣的是, 按下去應該要執行一個動作, 這個動作我們通常會寫成一個函數。 # In[19]: b = Button( description='按我', button_style='info', # 這風格還有 'success', 'warning', 'danger' 等等 width='100px' ) # In[20]: display(b) # 目前按一按沒有什麼特別效果, 我們為了示範, 先來寫個耍寶小程式。 # # 首先我們用 `HTML` 讀入一張圖。 # In[21]: img_html = HTML("") # In[22]: display(img_html) # 試著讓圖動一下。 # In[23]: display(img_html) for i in range(60): img_html.value = " " * i + "" sleep(0.1) # 接下來我們想按按鈕, 就讓這隻熊熊開始動。我們再度顯示按鈕和熊熊。 # In[24]: display(b) display(img_html) def on_button_clicked(b): for i in range(60): img_html.value = " " * i + "" sleep(0.1) b.on_click(on_button_clicked) # ## 5. 文字框輸入後... # # 大家還記得我們要做「拍拍機器人」。這就要用文字框輸入, 然後 `submit` 後機器人會回話。如下圖。 # # # # 首先, 我們先弄個文字框。 # In[25]: me = Text("輸入訊息...") me.description = "輸入" # 再來用盡洪荒之力, 把所有會的 CSS 都弄上去。一個風格是準備給自己的發言 (`style1`), 一個是給拍拍機器人 (`style2`)。 # In[26]: style1 = "

" style2 = "

" # 我們「高級」對話程式來了, 當文字框被 `submit`, 我們就要把我們說的話、拍拍機器人的回話顯示出來。 # In[27]: def pipi(sender): display(HTML(style1 + me.value + '


')) display(HTML(style2 + '拍拍' + '


')) me.value = '' # 告訴我們的文字輸入框, 如果按下 enter, 也就是 `submit`, 就執行 `pipi` 這個函數。 # In[28]: me.on_submit(pipi) # 最後 display 我們的輸入框就好了! # In[29]: display(me) # #### [練習] # 其實這拍拍機器人還有很多不完美的地方 (當然包括 AI, 但現在我們說的是界面上的問題), 想辦法改善它! # ## 6. 連結兩個 widgets # # 有時我們想同時可以用文字對話框輸入數字, 也可以用數值滑桿輸同一個數字, 這要怎麼做到呢? 這就要新開啟一個神秘套件叫 ` # In[30]: from traitlets import link # 設個數字輸入框、數值滑桿。 # In[31]: ftxt = FloatText() fsld = FloatSlider() # 設好連結, 把兩個 widgets 的物件同步。 # In[32]: mylink = link((ftxt, 'value'), (fsld, 'value')) # 顯示出來試試是不是真的同步了。 # In[33]: display(ftxt, fsld) # 我們也可以取消同步。 # In[34]: mylink.unlink() # ## 7. Layout # # 我們想排一排我們的 widgets, 可以用 `HBox`, `VBox`, `Tabs` 等等來達成。 # # # # In[35]: buttons = [Button(description=str(i)) for i in range(1,10)] # 稍稍設一下 9 個按鈕的風格。 # In[36]: for b in buttons: b.button_style = "info" b.width = "50px" # 顯示出來! # In[37]: groups = [buttons[3*i:3*i+3] for i in range(3)] # In[38]: layout = VBox([HBox(groups[0]), HBox(groups[1]), HBox(groups[2])]) # In[39]: display(layout) # #### [練習] # # 試試可不可以寫出一個 Jupyter 計算機! # ## 8. 延伸活動 # # 在哪裡還可以找到一些 `ipywidgets` 更深入的資訊、範例呢? 這裡介紹一些, 都是很適合閃電秀的主題哦。 # #### `ipywidgets` 官方文件 # # 通常官方文件都不是聽來很令人振奮的東西, 不過 `ipywidgets` 的官方文件目前還是大概包含最多資訊、包括一些基礎教學的地方。 # # [`ipywidgets` 官方文件](http://ipywidgets.readthedocs.io/) # # 比如說, 我們可以在這找到[所有可以用的 widgets 列表](http://ipywidgets.readthedocs.io/en/latest/examples/Widget%20List.html)。 # #### 進階應用 # # 這麼炫的工具當然也有人寫了進階應用的套件。我們來看三個例子: # # * [bqplot](https://github.com/bloomberg/bqplot): 可以做 2D 互動畫圖的函式庫。 # * [pythreejs](https://github.com/jovyan/pythreejs): 讓你在 Jupyter 中使用 [three.js](https://threejs.org/) 這個 JavaScript 3D 函式庫! # * [ipyleaflet](https://github.com/ellisonbg/ipyleaflet): 在 Jupyter 中用 [Leaflet](http://leafletjs.com/) 個互動地圖!