kivyMDチュートリアル其の肆什捌 Behaviors - ToggleButton篇

ハロー、Qiita!いかがお過ごしでしょうか。

本当に余寒(先週の続き)という言葉を生み出した人は凄いなぁとしみじみしつつ、
ブルブル震えながらこの投稿記事を書いております。体調などは崩してはないで
しょうか。

関東は豪雪だからﾁｭｳｲｾﾖ!と警戒情報が出ていましたが、ちょっと積もっただけで
何が警戒なんだろうと思うばかりでしたね。みなさんの区域は結構積もったので
しょうか。全然関係ない地域の人はすみませんが、腹筋でもなさって頂ければと
思います。

はい、ということで無事でなによりで、無事でなければこうしてのうのうと記事を
書くこともできません。ひとまず安心ということで、今週も元気にKivyMDのことを
やっていきたいと思います。今週はタイトルの通りで、ToggleButtonとなります。

では、レッツラゴ。

## ToggleButton

冒頭にいきなり説明文がありますね。見てみましょう。

> This behavior must always be inherited after the button’s Widget class 
> since it works with the inherited properties of the button class.

なにやら高校英語の例文みたいな冒頭文ですが、キーワードはずばりinherited
ですね。もうこれだけ見ると、テストの選択肢は狭まるのみです。KivyMD共通
テストがあればもう解答できるレベルです。

初めて見られた方はちんぷんかんぷんかもしれませんが、この継承というワードは
Behaviors章の1つのテーマとも言えるくらいです。というか今までkvに書いて
こなかったり継承しなかったりといったケースはありません(一部除く)。

次になりますが、コードの例も記載があります。

> example:

```python
class MyToggleButtonWidget(MDFlatButton, MDToggleButton):
    # [...]
    pass
```

MyToggleButtonWidgetの引数を見れば一目瞭然ですね。MDFlatButtonと
MDToggleButtonが継承され、これらが使用されていることが分かります。

### Example Code

勝手にセクション分けをしています。

ToggleButtonがなんなのかは触れこめていませんが、IT用語時点ではこのように
記載があります。

> トグルボタンとは、オンのときに押すとオフに、オフのときに押すとオンになる
> ボタンやスイッチのこと。メディアプレーヤーの再生ボタンなどによく見られる。

https://e-words.jp/w/%E3%83%88%E3%82%B0%E3%83%AB%E3%83%9C%E3%82%BF%E3%83%B3.html

KivyMD自体の定義は少し変わってくるかもしれませんが、オンとオフのときに挙動
が異なるということは共通して言えるかもしれません。あと、これまでに出てきた
ウィジェットとかで似ているのはChipとかでしょうか。

https://kivymd.readthedocs.io/en/latest/components/chip/

というか、Chip篇の中身変わりすぎてない...?というくらい惑わされていますが、
挙動としてはすごく似ているところがあります。ですが、Chipの場合は継承する
必要性がないことがあります。

ということで、実際に見てみた方がはやいと思うので、コード例を見てみましょう。

```python:xlviii/togglebutton.py
from kivy.lang import Builder

from kivymd.app import MDApp
from kivymd.uix.behaviors.toggle_behavior import MDToggleButton
from kivymd.uix.button import MDRectangleFlatButton, MDFillRoundFlatButton

KV = '''
Screen:

    MDBoxLayout:
        adaptive_size: True
        pos_hint: {"center_x": .5, "center_y": .5}

        MyToggleRectangleButton:
            text: "Show ads"
            group: "x"

        MyToggleRectangleButton:
            text: "Do not show ads"
            group: "x"

        MyToggleRectangleButton:
            text: "Does not matter"
            group: "x"

        MyToggleRoundButton:
            text: "Show ads"
            group: "y"

        MyToggleRoundButton:
            text: "Do not show ads"
            group: "y"

        MyToggleRoundButton:
            text: "Does not matter"
            group: "y"
'''


class MyToggleRectangleButton(MDRectangleFlatButton, MDToggleButton):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.background_down = self.theme_cls.primary_light


class MyToggleRoundButton(MDFillRoundFlatButton, MDToggleButton):
    def __init__(self, **kwargs):
        self.background_down = MDApp.get_running_app().theme_cls.primary_dark
        super().__init__(**kwargs)

class Test(MDApp):
    def build(self):
        return Builder.load_string(KV)


Test().run()
```

コード全文を掲載していますが、今回も先週同様カスタマイズをしております。

といっても大したことはやっていなく、MDFillRoundFlatButtonを継承させた
MyToggleRoundButtonを追加しているくらいです。ベースとしては何も増えて
いないと言っても過言ではありません。

kv自体はこれまで出てきたものを使っているので、特に触れ込むことはしません。
ですが、初めて見られた方はなんのこっちゃと思われるかもしれないので、もし
詳細を知りたいという方は以下の3リンクもしくは該当公式マニュアルを参照頂け
ればと思います。

https://qiita.com/virty/items/d5fa0a529912e6b0beb0

https://qiita.com/virty/items/b252e6fe039685eef208

https://qiita.com/virty/items/29d792d5ecf4ad0f86be

とりわけ今日のメインであるところは、冒頭でもありましたが以下の部分ではない
でしょうか。部分的にコードの方を抜粋します。

```python
class MyToggleRectangleButton(MDRectangleFlatButton, MDToggleButton):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.background_down = self.theme_cls.primary_light

class MyToggleRoundButton(MDFillRoundFlatButton, MDToggleButton):
    def __init__(self, **kwargs):
        self.background_down = MDApp.get_running_app().theme_cls.primary_dark
        super().__init__(**kwargs)
```

両方のクラスともMDToggleButtonを継承していることが分かりますね。あとは、
使うボタンによって何を継承するかを決めるのみです。ここで使っているものは
公式マニュアルでも使われているものになります。

あとはinitメソッドの中で選択されたときにどういう風にその状態を表示するか
ということをbackground_downプロパティに保持させます。それぞれtheme_cls
のprimary_light、primary_darkを選択しています。

これはコード外の話ですが、上記で使用したボタン以外に使用できるボタンが列挙
されています。ここでも全て引用として掲載をしておきます。

> You can inherit the MyToggleButton class only from the following classes

> * MDRaisedButton
> * MDFlatButton
> * MDRectangleFlatButton
> * MDRectangleFlatIconButton
> * MDRoundFlatButton
> * MDRoundFlatIconButton
> * MDFillRoundFlatButton
> * MDFillRoundFlatIconButton

全部で8つですね。Buttonに関してはほぼほぼ使用できるのではないかと思います。

### 結果

では、あれやこれや言ってきましたが、実際に動きを見てみた方がくっきりと分かり
やすいかと思います。動かした様子を以下に掲載しておきます。

![206.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82826/291ada65-2f73-bc7e-8c12-2167d17d3c88.gif)

正常に動くかなぁと思いきや、思わぬ発見ですね。MyToggleRectangleButtonに
関しては、再描画する際にどうやら元の文字が潰れてしまっているようです。これは
もしや自分のやり方にミスが?!と思って元々のコードを試してみたのですが、結果は
同じでした。

ということで、これは1.0にバージョン上げたときの際に確認する必要がありますね...
今後の課題が多くなるという、、まぁですが、次のバージョンでは直ってることを期待
したいですね。

### API - kivymd.uix.behaviors.toggle_behavior

まとめに入る前に、恒例行事をしておきます。

#### class kivymd.uix.behaviors.toggle_behavior.MDToggleButton(**kwargs)

> This mixin class provides togglebutton behavior. Please see the togglebutton 
> behaviors module documentation for more information.

> New in version 1.8.0.

今日のことの振り返りですね。New in version 1.8.0.ということが気になり
ますが、大きく1.8.0で変わるのでしょうか。

`background_down`

> Color of the button in rgba format for the ‘down’ state.

> background_down is a ColorProperty and is defaults to None.

本日唯一使用したプロパティになります。ボタンを押下したときと覚えれば覚え
やすいでしょうかね。デフォルトはNoneで意図的に設定しなければいけないもの
になります。

他には押してないときの_Normal、font_プロパティなどがあります。

## まとめ

はい、ということでいかがだったでしょうか。

ボタンが複数あって、何かを選択状態にしたいということがあるときはトグル
ボタンを使用してもよいのではないでしょうか。他にはSelectionControls
というものもありましたが、これについては設定画面などに有効です。

具体的な使用イメージを想像してみましたが、タブのような使い方になります
かね。ボタンだけでウィジェットの選択を変更したいといった、まぁそれもタブ
で使用されますが、ウィジェット全体を変更するのではなく、小規模のウィジェ
ットを変更したいときですかね。

では、今週はこのあたりにしたいと思います。来週はとうとう、1区切りが着い
てしまうTouch篇となります。今後の動向については来週まとめていきたいと
思います。ではまた、元気に来週お会いしましょう〜。

それでは、ごきげんよう。

## 参照

> Behaviors » ToggleButton
> https://kivymd.readthedocs.io/en/latest/behaviors/togglebutton/