kivyMDチュートリアル其の弍什漆 Components - SelectionControls篇

みなさん、おはこんばんは！元気ですかー？

やや元気が空回りしていますが、特に異常ではありません。
若干頭が重いことと、少々肩が痛いことは誤差の範囲という感じでしょうか。

さて、特にオリンピックが開催されたことくらいしかとりとめもなくさっそく
始めていきましょうかと言いたいところですが、お詫びしなければいけないこと
があります。

それほど、畏まっていうことでもないのですが、先週は**順番通りSelection-
Controlsをやっていく**と宣言していました。正しくはSelectionを飛ばして
SelectionControlsをやっていくということになります。お詫びして訂正します。
\# 理由は明確で動かなかっただけです

ということで、今日はSelectionControlsになります！今日も元気にやっていき
ますよー！(謎のテンション)

## SelectionControls

はい、お詫びしているにも関わらず、MaterialDesignのリンクは恒例で飛ばします。

HTMLとかでは、チェックボックスやラジオボタンに該当するものになりますね。それら
がなんかオシャンティー(死語)になっていると思ってもらえればと思いますが、それ以前
にそれほど以前のAndroidとかを使っていると別ですが結構見たことあるようなコンポー
ネントになります。マテリアルからかは断定できていませんが、スイッチ形式のコントロ
ールもあることも特徴と言えるでしょう。

kivyMDとしてもこのような冒頭文から始まっています。

> Selection controls allow the user to select options.

確かにあまり設定画面以外では見かけない気もしますね。

### MDCheckbox with group_Control state

おいおい、急にどうした?と言われそうですが、合体しました。ほとんどMDCheckboxと
変わらないのでこうしたというのがありますが、でもこうした結果よく分からんぞという
方はマニュアルにあるMDCheckbox単体のものを見ていただければと思います。というか
先にそっちを見たほうがいいかも・・・

さてコードもマニュアルから変更(というか厳密にいうと合体しただけ)をしているので、
マニュアル通りにいかず、さっそくコードに入っていきます。

```python:xxvii/mdcheckbox_withgroup_withcontrolstate.py
from kivy.lang import Builder

from kivymd.app import MDApp

KV = '''
<Check@MDCheckbox>:
    group: 'group'
    size_hint: None, None
    size: dp(48), dp(48)
    on_active: app.on_checkbox_active(*args)


MDFloatLayout:

    Check:
        active: True
        pos_hint: {'center_x': .4, 'center_y': .5}

    Check:
        pos_hint: {'center_x': .6, 'center_y': .5}
'''


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

    def on_checkbox_active(self, checkbox, value):
        if value:
            print('The checkbox', checkbox, 'is active', 'and', checkbox.state, 'state')
        else:
            print('The checkbox', checkbox, 'is inactive', 'and', checkbox.state, 'state')
```

なんか複雑なことをやってそうですが、単純明快、マニュアルを合体しただけに
なりますw

ではここからは恒例行事に入ります。

#### kv側

インポート文はとりとめもありませんので、省きます。
kv側で定義されているものを抜粋します。

```python
KV = '''
<Check@MDCheckbox>:
    group: 'group'
    size_hint: None, None
    size: dp(48), dp(48)
    on_active: app.on_checkbox_active(*args)


MDFloatLayout:

    Check:
        active: True
        pos_hint: {'center_x': .4, 'center_y': .5}

    Check:
        pos_hint: {'center_x': .6, 'center_y': .5}
'''
```

まずはMDFloatLayoutの配下にある、Checkウィジェットから。
これはまず最初に目の当たりにするのは、MDCheckboxを継承しているということ
ですね。

そして、プロパティで定義されているものは何かというと、group、size_hint、
size、on_activeになりますね。size_hintはお馴染み感しかありませんね。
不明な方は、Layout篇を辿るか、kivyから入門のほどを。

あとは、sizeについてはなんとなく分かるとは思いますが、説明文もありますし
ここで触れておきます。説明文についてはマニュアル通りですが、以下にて記載して
おきます。

:::note warn
Be sure to specify the size of the checkbox. By default, 
it is (dp(48), dp(48)), but the ripple effect takes up 
all the available space.
:::

これ使いたかっただけかと言われそうですが、それは確かかもしれませんw
まぁ、そんなことは置いておいて、デフォルト値が縦横dp(48)ということは分かり
ます。

後半は少し分かってないこともありますが、あぁなんだマニュアル通りのことかという
ことになります。これは動かしてみて分かったことですが、ただただリップルエフェクトの
大きさということで、値を変更してみるとこれの円形の大きさが変更されるだけになります。
まぁ、書いてある通りっちゃ書いてある通りなんですけども。

あとは、on_activeコールバックとgroupになります。on_activeはControl state
の話で、メインとしてはTestクラス側で触れる形となるので詳細はこの後で。ここでは
Checkウィジェットでコールバックを持たせる形を取っています。groupはなんでしょうね。
クラス側でも出てこないしで、これが何か分からないということが現状です。

あとは、ちゃんと説明できているか不明なCheckウィジェットがMDFloatLayoutによって
配置されていることでしょうか。手前で定義されている方に、初期表示時でチェックが付く
ようにactiveプロパティが定義されています。値はもちろんTrueに設定されていますね。
あとは触れるまでもないかもですが、pos_hintで位置付けされています。

#### Testクラス側

ということで、kv側は以上になります。

ここからは、Testクラス側に入っていきますが以下にて再掲しておきます。

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

    def on_checkbox_active(self, checkbox, value):
        if value:
            print('The checkbox', checkbox, 'is active', 'and', checkbox.state, 'state')
        else:
            print('The checkbox', checkbox, 'is inactive', 'and', checkbox.state, 'state')
```

buildメソッドなんかはこれまで通りになりますが、キモはon_checkbox_active
メソッドになります。先程のkv側でコールバックで指定していたところになります。
まぁ、これもマニュアル通りになるので特に触れるまでもないのですが、それを言って
しまうとこの投稿も意味なくなっちゃうので・・・

まず、このメソッドの引数としてはcheckboxとvalueの2つがあります。ここは見た
まんまになりますが、valueの値(チェックが入っているかいないか)によってprint文
でcheckboxインスタンスのメモリ番地とステータスを出力しているだけになります。ス
テータスについては結果の方で詳細を。

### 結果

今日もさくさくと進んできましたが、さっそく結果の方に移りたいと思います。
まずは、初期表示がどうなるか見てみましょう。

![130.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82826/f8a772fa-1d55-9c8c-1b5d-41c589c21064.png)

ラジオボタンでのウィジェットが2つ表示され、初めにactiveプロパティをTrueに
設定しておいたウィジェット(画面左側)がチェック付きで表示されます。また、チェ
ックを違う方に付けてみると、

![131.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82826/60060d6e-7d8f-7e77-3acc-791764d11b6e.png)

というようにチェックが別のものに付くようになります。

今度は、なんだかよく分からないと言っていたgroupプロパティですが、こちらを
コメントアウトしてみて動作がどうなるか見てみます。

![132.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82826/6df1d44f-b3b4-fc42-73c3-ee7d826248ea.png)

あらま、という感じになりますがまずラジオボタンがチェックボックスに切り替わっています。
なるほど、グルーピングすれば勝手にラジオボタンのように切り替わるというのですね。

さらにこれを初期表示でチェックが付いているものと異なるボックスを押してみると、

![133.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82826/7679c63b-deb5-ae84-aa89-2fe3c4ed5606.png)

まぁ、それはそうかと言わんばかりに両方ともチェックが付いてしまいました。
なので、ラジオ・チェックボックスの切り替えはgroupプロパティで切り替え
られるとみてもらった方がいいかもしれません。

さらに、さっき言ってたステータスの件を見てみましょう。今度はgroupプロパティを
設定したところに戻ります。初期表示から2~3回ほど切り替えたときのprintで出力さ
れたようすを以下に載せておきます。

```text
[INFO   ] [GL          ] NPOT texture support is available
The checkbox <kivy.factory.Check object at 0x110731ed0> is active and down state
[INFO   ] [Base        ] Start application main loop
The checkbox <kivy.factory.Check object at 0x110731ed0> is inactive and normal state
The checkbox <kivy.factory.Check object at 0x1107422d0> is active and down state
The checkbox <kivy.factory.Check object at 0x1107422d0> is inactive and normal state
The checkbox <kivy.factory.Check object at 0x110731ed0> is active and down state
The checkbox <kivy.factory.Check object at 0x110731ed0> is inactive and normal state
The checkbox <kivy.factory.Check object at 0x1107422d0> is active and down state
```

Start application main loopがなされる前に1回、on_checkbox_activeメソッド
が実行されていますね。

これは別途調査をして分かったことですが、Checkウィジェットを定義したときにbuild
メソッドの中でkvを読み込んだあと、インスタンスが生成され自動的にon_check_active
メソッドが動いているような気がしてなりません。根拠としてはそれぞれのウィジェット
(MDFloatLaytoutの配下)にコールバックを定義すると、このような挙動にならなかったため
です。

Start appli~以降は挙動としては同じですね。切り替わったときには元のウィジェットが
normal state(チェックがオフ(inactive))になり、切り替え先ではdown state(チェック
がオン(active))になります。切り替え時には、groupプロパティでまとめられているところが
全てprint出力の対象となります。groupプロパティがないときはそれぞれのウィジェットごとに
出力されることになりました。

### MDSwitch

ということで、終わった感もありますがまだ続きます。Switchの方ですね。
こちらもさっそくコードに移っていきます。それほど触れる量は多くはありません。

```python:xxvii/mdswitch.py
from kivy.lang import Builder

from kivymd.app import MDApp

KV = '''
MDFloatLayout:

    MDSwitch:
        pos_hint: {'center_x': .5, 'center_y': .6}

    MDSwitch:
        pos_hint: {'center_x': .5, 'center_y': .4}
        width: dp(64)
'''


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


Test().run()
```

こちらの方はマニュアルより少しだけ変更になります。というかこちらもNoteパネルで
指し示したところをくっつけただけになります。オリジナリティは安定して0です。

ここも先程のMDCheckboxを見ていただいたら、触れるまでもないかもしれません。
というか触れるところが、kvの中の2つ目のMDSwitchウィジェットくらいしかあり
ません。こちらはwidthがデフォルトからdp(64)に変更しているのみになります。

### 結果

ということで、こちらも結果の方に移りたいと思います。

![134.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82826/9ce06158-2a5d-fd6a-dffc-c865b45cafd5.png)

初期表示はこのような感じになります。dp(64)に設定したウィジェットは横に伸びて
いる印象は強いですよね。そして、両方ともスイッチを切り替えると、

![135.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82826/299e965d-4e54-0819-aee5-83d6b7ec8f29.png)

このようになりました。んー、これだとデフォルトでことは足りそうな気がします。
ご利用は計画的に。

### API - kivymd.uix.selectioncontrol

ということでまとめの手前に使用したAPIについて引用しておきます。
ここでは、さらっといきます。

#### class kivymd.uix.selectioncontrol.MDCheckbox(**kwargs)

> Class implements a circular ripple effect.

円状に広がるリップルエフェクトが実装されています。

`active`

> Indicates if the checkbox is active or inactive.

> active is a BooleanProperty and defaults to False.

コードでも動作でも出たプロパティになりますね。デフォルトはもちろんFalseに
なります。

`checkbox_icon_normal`
`checkbox_icon_down`
`radio_icon_normal`
`radio_icon_down`
※ 説明文は割愛

表示を変えられるようですね。変え方も知りたいのにな・・・
まぁ、これはコードをみてくれよなということでしょうか。

#### class kivymd.uix.selectioncontrol.MDSwitch(**kwargs)

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

ボタンとのmixinであるようです。ということなのでそちらの方の詳細を知りたい、
ということになればマニュアルのButtonページかButton篇を見るようにすると知識
ネットワークが構築されそうです。Button篇はこちら(マニュアルもここから辿れます)。

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

`active`

これはMDCheckboxと同じなので、特に説明は必要なさそうですね。

あとはMDCheckbox同様、押したときの振る舞いを変えられるのとテーマカラーなどが
変更出来そうです。時間があればこの辺も見たかったなぁ・・・

## まとめ

ということで以上になります！いかがだったでしょうか。

思ったより時間が掛かったというはあるんですけれども、まぁそんなどうでもよいことは
よくて、設定画面とかを作り込むケースだと必須のようなウィジェットになるかもしれません。

あとは、リストとどのように組み合わせられそうかなとか見たかったのですが、残念ながら
タイムアップ・・・実際のアプリ作成のときにお披露目という感じになりそうです。。

では、今日はここまでとなります。次回は**ちゃんと順番**通りにSlider篇という予定です。
次回、お楽しみに！

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

## 参照

> Components » SelectionControls
> https://kivymd.readthedocs.io/en/latest/components/selectioncontrols/