有很多同學問到, 我們用 ipywidgets
的 interact
或 interact_manual
可以做得更漂亮、更客制化我們想要的功能嗎?
答案是肯定的。
這就要用到眾多很酷的 widgets。雖然每次設定麻煩一點點, 但不管是種類還是自由度都高很多。
我們先來引入一個 widget
, 然後大概介紹這有可能可以做什麼。
from ipywidgets.widgets import *
from IPython.display import display
這裡要注意, 有個 widget
叫 HTML
, 但這和之前我們引入的
from IPython.display import HTML
是不同的!
html = HTML('<h1>Hi</h1>')
display(html)
HTML(value='<h1>Hi</h1>')
這目前看來一樣? 不一樣是我們可以 display 很多次, 而且你可以之後修改顯示內容。
display(html)
HTML(value='<h1>Hi</h1>')
html.value = '<h1 style="color:red;">你好</h1>'
你會發現, 兩次的 display 都改了!! 這有什麼好處呢? 這就是我們放上一個在網頁上的 widget, 我們可以去改變它呈現的樣子。
為了示範一個「小動畫」例子, 我們做一隻會跑的蟲。為了不要讓蟲蟲「瞬間移動」, 我們引入 sleep
。
from time import sleep
worm = HTML('<div style="color:green;">oooo</div>')
display(worm)
for i in range(80):
htmlbase = '<div style="color:green;">%s</div>'
html = htmlbase % (" " * (i+1) + "oooo")
worm.value = html
sleep(0.2)
HTML(value='<div style="color:green;">oooo</div>')
這裡說明一下, 我們用到的
是 HTML 的空白。直接打空白你會發現 HTML 不理你, 當然你也可以直接打「全型的空白」, 因為 HTML 基本上當成一個文字, 所以會乖乖顯示。
而
sleep(0.2)
是說讓 Python 「睡」 0.2 秒, 再繼繼下一個動作。
有同學問到, 可以自動讓蟲蟲爬回來可以嗎? 當然可以啊, 試試看吧 :)
進度條就是像我們下載大型檔案時, 電腦會出現目前已進行多少百分比的進度那個指示條。你可以看到反正每次要使用一個 widget, 就是先宣告一個 widget, 然後用 display
顯示出來。再來就是可以改一些裡面的設定, 最常改的就是 value
。
p = IntProgress()
display(p)
IntProgress(value=0)
這空空的進度條當然沒什麼好看的, 我們可以設任一個 0 到 100 的數字給它, 比如說:
p.value=55
當然會動的進度表更有感覺 :)
為了看清楚, 我們再一次顯示同一個進度表, 注意和之前的進度表是完全連動的!
display(p)
for i in range(101):
p.value = i
sleep(0.1)
IntProgress(value=55)
我們回來看看之前用 interact
就會出現的數值滑桿。我們為何要自已呼叫呢? 因為更可以完全客制化, 更彈性的運用。
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"
display(s)
IntSlider(value=1, max=10, min=1, style=SliderStyle(handle_color='#44AF69'))
倒底有什麼參數可以改呢? 我們可以列出來看看。
s.keys
['_dom_classes', '_model_module', '_model_module_version', '_model_name', '_view_count', '_view_module', '_view_module_version', '_view_name', 'continuous_update', 'description', 'description_tooltip', 'disabled', 'layout', 'max', 'min', 'orientation', 'readout', 'readout_format', 'step', 'style', 'value']
而且, 我們還可以客制化的精美數值滑桿用到之前的 interact
中。
from ipywidgets import interact
def f(x):
print(x)
interact(f, x=s);
interactive(children=(IntSlider(value=1, description='x', max=10, min=1, style=SliderStyle(handle_color='#44AF…
互動介面中, 我們常常用到的按鈕, 應該有個吧? 那是當然的。按鈕和之前的應用有點不一樣的是, 按下去應該要執行一個動作, 這個動作我們通常會寫成一個函數。
b = Button(
description='按我',
button_style='info', # 這風格還有 'success', 'warning', 'danger' 等等
width='100px'
)
display(b)
Button(button_style='info', description='按我', style=ButtonStyle())
目前按一按沒有什麼特別效果, 我們為了示範, 先來寫個耍寶小程式。
首先我們用 HTML
讀入一張圖。
img_html = HTML("<img src='images/numpy.png'>")
display(img_html)
HTML(value="<img src='images/numpy.png'>")
試著讓圖動一下。
display(img_html)
for i in range(60):
img_html.value = " " * i + "<img src='images/numpy.png'>"
sleep(0.1)
HTML(value="<img src='images/numpy.png'>")
接下來我們想按按鈕, 就讓這隻熊熊開始動。我們再度顯示按鈕和熊熊。
display(b)
display(img_html)
def on_button_clicked(b):
for i in range(60):
img_html.value = " " * i + "<img src='images/numpy.png'/>"
sleep(0.1)
b.on_click(on_button_clicked)
Button(button_style='info', description='按我', style=ButtonStyle())
HTML(value=" &n…
me = Text("輸入訊息...")
me.description = "輸入"
再來用盡洪荒之力, 把所有會的 CSS 都弄上去。一個風格是準備給自己的發言 (style1
), 一個是給拍拍機器人 (style2
)。
style1 = "<p style='position:relative; left:80px; padding:10px; border-radius:25px; color:white; background:#4080FF; width:200px;'>"
style2 = "<p style='padding:10px; border-radius:25px; background:#F1F0F0; width:200px;'>"
我們「高級」對話程式來了, 當文字框被 submit
, 我們就要把我們說的話、拍拍機器人的回話顯示出來。
def pipi(sender):
display(HTML(style1 + me.value + '</p> <br>'))
display(HTML(style2 + '拍拍' + '</p> <br>'))
me.value = ''
告訴我們的文字輸入框, 如果按下 enter, 也就是 submit
, 就執行 pipi
這個函數。
me.on_submit(pipi)
最後 display 我們的輸入框就好了!
display(me)
Text(value='輸入訊息...', description='輸入')
其實這拍拍機器人還有很多不完美的地方 (當然包括 AI, 但現在我們說的是界面上的問題), 想辦法改善它!
有時我們想同時可以用文字對話框輸入數字, 也可以用數值滑桿輸同一個數字, 這要怎麼做到呢? 這就要新開啟一個神秘套件叫 `
from traitlets import link
設個數字輸入框、數值滑桿。
ftxt = FloatText()
fsld = FloatSlider()
設好連結, 把兩個 widgets 的物件同步。
mylink = link((ftxt, 'value'), (fsld, 'value'))
顯示出來試試是不是真的同步了。
display(ftxt, fsld)
FloatText(value=0.0)
FloatSlider(value=0.0)
我們也可以取消同步。
mylink.unlink()
我們想排一排我們的 widgets, 可以用 HBox
, VBox
, Tabs
等等來達成。
buttons = [Button(description=str(i)) for i in range(1,10)]
稍稍設一下 9 個按鈕的風格。
for b in buttons:
b.button_style = "info"
b.width = "50px"
顯示出來!
groups = [buttons[3*i:3*i+3] for i in range(3)]
layout = VBox([HBox(groups[0]), HBox(groups[1]), HBox(groups[2])])
display(layout)
VBox(children=(HBox(children=(Button(button_style='info', description='1', style=ButtonStyle()), Button(button…
試試可不可以寫出一個 Jupyter 計算機!
在哪裡還可以找到一些 ipywidgets
更深入的資訊、範例呢? 這裡介紹一些, 都是很適合閃電秀的主題哦。
ipywidgets
官方文件¶通常官方文件都不是聽來很令人振奮的東西, 不過 ipywidgets
的官方文件目前還是大概包含最多資訊、包括一些基礎教學的地方。
比如說, 我們可以在這找到所有可以用的 widgets 列表。