kivyを使ってGUIプログラミング ~その4 ボタンいろいろ~

#はじめに
kivyでは様々なボタンがあります。普通に使えるものから、ちょっとよくわからないものまで。
そこで今回は、特に使えそうなものをピックアップして紹介したいと思います。細かいところまでは、言及しません。今までのように、kivyのuiを用いて何か作って紹介するといった感じではないです。この記事では、簡単な使い方の例だけを示します。ソースは公式のリファレンスの受け売りです。詳しい使い方はリファレンスを参照していただきたいです！

※今回のボタンの定義は、押したらなんかなる奴です。細かいことは抜きにします！
https://www.weblio.jp/content/button

# 普通のボタンたち

### [kivy.uix.Button](https://kivy.org/doc/stable/api-kivy.uix.button.html)

紹介するまでもないと思いますが、普通のボタンです。

![button.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/421817/933b6598-3b16-4c27-080e-397d19031e1f.gif)

``` python:button_sample.py
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.togglebutton import ToggleButton
from kivy.uix.behaviors import ToggleButtonBehavior

class Test(BoxLayout):
    def __init__(self, **kwargs):
        super(Test, self).__init__(**kwargs)

        # ラベルの定義
        self.label = Label(text="OFF")
        self.add_widget(self.label)

        # ボタンの定義、押した時と話した時の処理
        self.button = Button(on_press=self.press, on_release=self.release, text="Press!")
        self.add_widget(self.button)

    #押した時
    def press(self, btn):
        self.label.text = "This is Button!"

    #話した時
    def release(self, btn):
        self.label.text = "OFF"


class Sample(App):

    def build(self):
        return Test()

Sample().run()
```

### [kivy.uix.togglebutton](https://kivy.org/doc/stable/api-kivy.uix.togglebutton.html)

押したらON状態、OFF状態が確認できるボタンです。
押されているかどうかは、トグルボタンの```state```という変数の```down```と```normal```で判別できます。また、```group```を設定することで、ラジオボタン的な使い方もできるようです。

画像にトグルボックス的な挙動を付与できたりもするらしいです。（未検証）
https://kivy.org/doc/stable/api-kivy.uix.behaviors.togglebutton.html#kivy.uix.behaviors.togglebutton.ToggleButtonBehavior

![toggle.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/421817/a328d159-325c-dbbe-3abb-8796319c59b7.gif)


```python
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.uix.togglebutton import ToggleButton

class Test(BoxLayout):
    def __init__(self, **kwargs):
        super(Test, self).__init__(**kwargs)

        # ラベルの定義、
        self.label = Label(text="OFF")
        self.add_widget(self.label)

        # トグルボタンの定義
        self.toggle = ToggleButton(on_press=self.t_press, text="Press!")
        self.add_widget(self.toggle)

        # チェックボックスとして扱うトグルボタンを別で用意したボックスレイアウトに貼り付ける
        self.toggle_box = BoxLayout()
        self.t1 = ToggleButton(group="g1", on_release=self.toggle_check,  text="toggle 1")
        self.t2 = ToggleButton(group="g1", on_release=self.toggle_check, text="toggle 2")
        self.t3 = ToggleButton(group="g1", on_release=self.toggle_check, text="toggle 3")
        self.toggle_box.add_widget(self.t1)
        self.toggle_box.add_widget(self.t2)
        self.toggle_box.add_widget(self.t3)
        self.add_widget(self.toggle_box)

    def t_press(self, btn):
        if btn.state == "down":
            self.label.text = "This is Toggle Button!"
        if btn.state == "normal":
            self.label.text = "OFF"

    def toggle_check(self, btn):
        self.label.text = btn.text

class Sample(App):

    def build(self):
        return Test()

Sample().run()
```

### [kivy.uix.checkbox](https://kivy.org/doc/stable/api-kivy.uix.checkbox.html)

ラジオボタンとチェックボックスです。 トグルボタンと似たような挙動をしています。
```group```を設定すると、ラジオボタンになり、設定しないと、チェックボックスになります。（下記ソースのコメント部を外してもらうと確認できると思います。）
トグルボタンとは違い押されているかどうかは、```active```という変数からTrue Falseで確認できます。

![check.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/421817/e809f3aa-a9e9-a0a4-3060-52e3a2d07977.gif)


```python
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.uix.checkbox import CheckBox


class Test(BoxLayout):
    def __init__(self, **kwargs):
        super(Test, self).__init__(**kwargs)

        self.orientation = "vertical"
        # ラベルの定義、スクリーンに貼り付け
        self.label = Label(text="OFF")
        self.add_widget(self.label)

        # チェックボックスとして扱うトグルボタンを別で用意したボックスレイアウトに貼り付ける
        self.checkbox_box = BoxLayout(orientation="horizontal")

        # チェックボックスを定義
        self.t1 = CheckBox()
        self.t2 = CheckBox()
        self.t3 = CheckBox()

        # ラジオボタンを定義
        # self.t1 = CheckBox(group="g1")
        # self.t2 = CheckBox(group="g1")
        # self.t3 = CheckBox(group="g1")

        self.checkbox_box.add_widget(self.t1)
        self.checkbox_box.add_widget(self.t2)
        self.checkbox_box.add_widget(self.t3)

        #チェックボックを押した時の処理
        self.t1.bind(active=self.on_checkbox_active)
        self.t2.bind(active=self.on_checkbox_active)
        self.t3.bind(active=self.on_checkbox_active)

        self.add_widget(self.checkbox_box)

    def on_checkbox_active(self, instance, value):
        self.label.text = "Left      : {}\n" \
                          "Center : {}\n" \
                          "Right    : {}\n".format(self.t1.state, self.t2.state, self.t3.state)

class Sample(App):

    def build(self):
        return Test()

Sample().run()
```

# ボタンっぽいもの
上で紹介したものは、ちゃんとボタンでしたが、下記で紹介するのは、ボタンを使って何かしてるものだと認識だと思います。

### [kivy.uix.spinner](https://kivy.org/doc/stable/api-kivy.uix.spinner.html)

コンボボックスです。上下どちらかにスペースを開けてあげないと、リストが開けないことに注意してください。

![comb.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/421817/8bc144c6-b389-78cf-a378-ab2d4d0b94ac.gif)


```python
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.dropdown import DropDown

class Test(BoxLayout):
    def __init__(self, **kwargs):
        super(Test, self).__init__(**kwargs)

        self.label = Label(text="test")
        self.add_widget(self.label)

        self.dropdown = DropDown()
        for index in range(10):

            btn = Button(text='Value %d' % index, size_hint_y=None, height=44)

            # 定義したボタンを押した時の処理
            btn.bind(on_release=lambda btn: self.dropdown.select(btn.text))

            # dropdownにボタンを載せる
            self.dropdown.add_widget(btn)

        self.mainbutton = Button(text="main", size_hint=(1, 0.1), pos_hint={"y": 0.9})
        self.mainbutton.bind(on_release=self.dropdown.open)

        self.add_widget(self.mainbutton)
        self.dropdown.bind(on_select=self.press)

    def press(self, instance, x):
        self.mainbutton.text = x
        self.label.text = "Press : {}".format(x)

class Sample(App):

    def build(self):
        return Test()

Sample().run()
```

### [kivy.uix.dropdown](https://kivy.org/doc/stable/api-kivy.uix.dropdown.html)

押したらドロップダウンリストが出てくるやつです。
コンボボックスと似てますが、こっちの方が開いたボタンに機能が付けることができるため、自由度が高いと思います。僕はうまく使えませんでしたが。。。

![list.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/421817/3e659b36-b6fa-1e19-7063-9bd9b2317f7e.gif)


```python
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.dropdown import DropDown

class Test(BoxLayout):
    def __init__(self, **kwargs):
        super(Test, self).__init__(**kwargs)

        self.label = Label(text="test")
        self.add_widget(self.label)

        self.dropdown = DropDown()
        for index in range(10):

            btn = Button(text='Value %d' % index, size_hint_y=None, height=44)

            # 定義したボタンを押した時の処理
            btn.bind(on_release=lambda btn: self.dropdown.select(btn.text))

            # dropdownにボタンを載せる
            self.dropdown.add_widget(btn)

        self.mainbutton = Button(text="main", size_hint=(1, 0.1), pos_hint={"y": 0.9})
        self.mainbutton.bind(on_release=self.dropdown.open)

        self.add_widget(self.mainbutton)
        self.dropdown.bind(on_select=self.press)

    def press(self, instance, x):
        self.mainbutton.text = x
        self.label.text = "Press : {}".format(x)

class Sample(App):

    def build(self):
        return Test()

Sample().run()![button.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/421817/d0665bf7-f6e7-0a4b-fb6d-bce3683092ae.gif)

```

### [kivy.uix.switch](https://kivy.org/doc/stable/api-kivy.uix.switch.html)

スイッチです。使ったことはありません。
挙動自体はチェックボックスとほぼ同じだと思います。ボタンを持ってスライドさせることもできるので、ちょっと面白いと思いましたw

![switch.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/421817/28b51375-0672-5843-02e1-8ad365e280b8.gif)


```python
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.uix.switch import Switch


class Test(BoxLayout):
    def __init__(self, **kwargs):
        super(Test, self).__init__(**kwargs)

        self.label = Label(text="test")
        self.add_widget(self.label)

        self.switch = Switch()
        self.switch.bind(active=self.switch_check)
        self.add_widget(self.switch)

    def switch_check(self, instance, value):
        if value:
            self.label.text = "ON"
        else:
            self.label.text = "OFF"


class Sample(App):

    def build(self):
        return Test()

Sample().run()
```

### [kivy.uix.accordion](https://kivy.org/doc/stable/api-kivy.uix.accordion.html)

ビロ〜んと出てくる、リストです。これも使ったことありません。
リストの中に何か処理とか入れたい場合には、```Accordion```の子要素である```AccordionImems```の宣言時に```ids```を入れるか、配列とかで保持しとけばできるかもしれないですね。(未検証)

![acc.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/421817/1e24c024-cbd1-5459-2141-648a26fdb8f1.gif)


```python
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.uix.accordion import Accordion, AccordionItem

class Test(BoxLayout):
    def __init__(self, **kwargs):
        super(Test, self).__init__(**kwargs)

        self.label = Label(text="test")
        self.add_widget(self.label)

        self.accordion = Accordion(orientation='vertical')
        #Accodionの中身を定義
        for x in range(5):
            item = AccordionItem(title='Title %d' % x)
            item.add_widget(Label(text='Very big content\n' * 10))
            self.accordion.add_widget(item)

        self.add_widget(self.accordion)


class Sample(App):

    def build(self):
        return Test()

Sample().run()
```

### [kivy.uix.tabbedpanel](https://kivy.org/doc/stable/api-kivy.uix.tabbedpanel.html)

タブを切り替えるボタンです。というよりもうこれボタンじゃないと思います。これはパネルですね。画面繊維を実装せずに画面の切り替えが簡単にできるので、便利なクラスだと思います。

![panel.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/421817/4a6b100e-8711-bd6c-677b-5743666078a9.gif)


```python
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.uix.tabbedpanel import TabbedPanel, TabbedPanelItem

class Test(BoxLayout):
    def __init__(self, **kwargs):
        super(Test, self).__init__(**kwargs)

        self.tabbedPanel = TabbedPanel(do_default_tab=False)

        #TabbedPanelに載せるパネルの定義
        self.panel1 = TabbedPanelItem(text="tab 1")
        self.panel1.add_widget(Label(text="This is Panel 1"))

        #TabbedPanelに載せるパネルの定義
        self.panel2 = TabbedPanelItem(text="tab 2")
        self.panel2.add_widget(Label(text="This is Panel 2"))

        #TabbedPanelに載せる
        self.tabbedPanel.add_widget(self.panel1)
        self.tabbedPanel.add_widget(self.panel2)

        #Appに載せる
        self.add_widget(self.tabbedPanel)


class Sample(App):

    def build(self):
        return Test()

Sample().run()
```


#まとめ
紹介といっておきながら今まで触ったことのないボタン(？)に触れることのできる良い機会となりました。細々した内容については全く触れず簡単に紹介いたしましたが今回の紹介したボタンを別の機会で使える日が来るようもう少し勉強しておきたいと感じました。

#参考文献
[公式リファレンス](https://kivy.org/doc/stable/api-index.html)