ipywidgetsでウィジェットのスタイルやレイアウトを調整する

JupyterでインタラクティブなGUI作ろうとしたけど、スライダーの幅が小さくて使いづらかったり、複数のコントロールを配置する方法が分からなかったりしたので調べてみた。

# ウィジェットのスタイルの調整
CSSライクな記述でスタイルを調整できます

## 基本形
幅が狭く操作しづらいので、いろいろ調整したい

```python
from ipywidgets import IntSlider

IntSlider(min=2000, max=2020,step=1,value=2010, description="year1: ")
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69163/e50dcafe-1a0c-2401-687b-d38ba4bbe830.png)

## 幅と高さを変えてみる
幅を60%指定、高さを100px指定にします。

```python
from ipywidgets import IntSlider, Layout

IntSlider(min=2000, max=2020,step=1,value=2010, description="year1: ",
                         orientation='horizontal',
                         layout=Layout(width='60%', height='100px'))
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69163/8ffe14f9-f5da-ef2d-5c69-365f5434757a.png)

## Borderもつけてみる
ついでに枠線もつけてみます。

```python
from ipywidgets import IntSlider, Layout

IntSlider(min=2000, max=2020,step=1,value=2010, description="year1: ",
                         orientation='horizontal',
                         layout=Layout(width='60%', height='100px', border='solid'))
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69163/48b52cdc-7500-8062-64ec-81b33e2f2c6c.png)


## その他スタイルの調整
ウィジェットごとに固有なスタイルもあります。
例えば、スライダーのハンドルに色をつけることができる。

```python
from ipywidgets import IntSlider

year1 = IntSlider(min=2000, max=2020,step=1,value=2010, description="year1: ")
year1.style.handle_color = 'lightblue'
year1
```
ハンドルが薄い青色になりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69163/2f119f9f-9fb1-5114-3ba8-5193396fc8c6.png)

利用可能なスタイルは以下で確認できる。

```python
year1.style.keys
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69163/ae3ff727-598c-05ea-e18c-2ba7c41972d0.png)

他にもいろいろなスタイルを調整できます。
公式ドキュメントに利用可能なスタイルが記載されています。
[Layout and Styling of Jupyter widgets — Jupyter Widgets 7.5.1 documentation]( https://ipywidgets.readthedocs.io/en/latest/examples/Widget%20Styling.html)

# レイアウトを変える
複数のウィジェットがある場合に、レイアウトにそって並べることもできます。

## 横と棚に並べる
横方向のコンテナ(HBox)、縦方向のコンテナ(VBox)にウィジェットを配置できる。

```python
from ipywidgets import IntSlider, Layout, HBox, VBox

year1 = IntSlider(min=2000, max=2020,step=1,value=2010, description="year1: ")
year2 = IntSlider(min=2000, max=2020,step=1,value=2010, description="year2: ")
year3 = IntSlider(min=2000, max=2020,step=1,value=2010, description="year3: ")
year4 = IntSlider(min=2000, max=2020,step=1,value=2010, description="year4: ")
year5 = IntSlider(min=2000, max=2020,step=1,value=2010, description="year5: ")
year6 = IntSlider(min=2000, max=2020,step=1,value=2010, description="year6: ")

VBox([HBox([year1,year2,year3]),HBox([year4,year5,year6])])
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69163/53e57c55-898c-8eea-3a6f-356c8314d25f.png)


## 2×2で並べる
2×2のレイアウトでウィジェットを配置できます。

```python
from ipywidgets import IntSlider, TwoByTwoLayout
year1 = IntSlider(min=2000, max=2020,step=1,value=2010, description="year1: ")
year2 = IntSlider(min=2000, max=2020,step=1,value=2010, description="year2: ")
year3 = IntSlider(min=2000, max=2020,step=1,value=2010, description="year3: ")
year4 = IntSlider(min=2000, max=2020,step=1,value=2010, description="year4: ")

TwoByTwoLayout(top_left=year1,
               top_right=year2,
               bottom_right=year3,
               bottom_left=year4)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69163/4d9d826a-e2ee-eb6b-947c-7d126c322812.png)


## グリッドに並べる
n × mの任意のサイズのグリッドにウィジェットを配置できます。

```python
from ipywidgets import IntSlider, GridspecLayout

grid = GridspecLayout(2, 3)

grid[0,0] = IntSlider(min=2000, max=2020,step=1,value=2010, description="year1-1: ")
grid[0,1] = IntSlider(min=2000, max=2020,step=1,value=2010, description="year1-2: ")
grid[0,2] = IntSlider(min=2000, max=2020,step=1,value=2010, description="year1-3 ")
grid[1,0] = IntSlider(min=2000, max=2020,step=1,value=2010, description="year2-1: ")
grid[1,1] = IntSlider(min=2000, max=2020,step=1,value=2010, description="year2-2: ")
grid[1,2] = IntSlider(min=2000, max=2020,step=1,value=2010, description="year2-3: ")

grid
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69163/73a6364d-8846-57f0-2aa5-574840434fdc.png)

## 他のレイアウト
公式サイトの以下のドキュメントに記載があります。
アプリ風のApp Layoutなども使えます。
[Using Layout Templates — Jupyter Widgets 7.5.1 documentation]( https://ipywidgets.readthedocs.io/en/latest/examples/Layout%20Templates.html)

# まとめ
Jupyter使う場合は、凝ったUI作りこむ必要はないけど、コントロールを使いやすくしたり、ちょっとだけ見た目よくすると、より使いやすいと思います。
そういうことやりたい方の参考になればうれしいです。