Kivyで簡単にドロップダウンリストを実装する方法

みなさまおはこんばんにちは、せなです

今回はKivyでドロップダウンリストを実装する方法について説明したいと思います

始めに

Kivyでは「DropDown」が存在しますが、そちらは使用しません
代わりに、「Spinner」を使用して、説明していきます

SpinnerはDropDownよりも簡単に実装できます(汎用性は多少、失われてしましますが…)

環境

Python:3.7
Kivy:1.11.1

Spinnerの基本構文

「Spinner」は設定した値を、ドロップダウンリストから選択することで表示することができる、複合UXウィジェットです

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout


class RootWidget(BoxLayout):
    pass


class TestSpinnerApp(App):
    def build(self):
        return RootWidget()


if __name__ == '__main__':
    TestSpinnerApp().run()
<RootWidget>
    Spinner:
        size_hint_y: None
        size: 100, 30
        pos_hint: {'y': .9}
        text: 'Home'
        values: 'Home', 'Report', 'Enquiry', 'Agreement', 'Other'

ドロップダウンリスト内でのイベント

Spinnerには「option_cls」が用意されていますが、「Kivy: 1.11.1」現在正しい動作が期待できないようです

どうしても、ドロップダウンリスト内でのイベント処理を行いたい場合には、以下のサイトを参考にしてみてください(私は挫折しました…

リンク:how to set the buttons size inside a spinner in kivy? – Stack Overflow

以下のコードは試行錯誤した、結果です
※適当に書いているので、見栄えが良くありません、お許しください

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import ObjectProperty
from kivy.uix.spinner import Spinner
from kivy.uix.button import Button


class RootWidget(BoxLayout):
    item_list = ObjectProperty(None)
    label_text = ObjectProperty(None)
    input_text = ObjectProperty(None)

    def widgets_list_add(self):
        self.item_list.values.append(self.input_text.text)

    def label_text_change(self):
        self.label_text.text = self.item_list.text


class SpinnerButton(Button):
    pass


class MySpinner(Spinner):
    option_cls = ObjectProperty(SpinnerButton)


class TestSpinnerApp(App):
    def build(self):
        return RootWidget()


if __name__ == '__main__':
    TestSpinnerApp().run()
<RootWidget>
    orientation: "vertical"
    item_list: item_list
    label_text: label_text
    input_text: input_text

    BoxLayout:
        size_hint_y: None
        size: 100, 35
        Label:
            text: 'Title'

    BoxLayout:
        size_hint_y: None
        size: 100, 45
        TextInput:
            id: input_text
            text_hint: 'Hint'
        Button:
            text: 'Add'
            on_release: root.widgets_list_add()

    BoxLayout:
        MySpinner:
            id: item_list
            size_hint_y: None
            size: 100, 30
            pos_hint: {'y': .885}
            text: 'Home'
            values: 'Home', 'Work', 'Other', 'Custom'
        Button:
            size_hint_x: None
            text: 'OK'
            on_release: root.label_text_change()

    BoxLayout:
        Label:
            id: label_text
            size: 100, 40
            pos_hint: {'y': .8}
            text: ''
            font_size: 50
            text_size: 200, None

<SpinnerButton>:
    size_hint_y: None
    size: 100, 30