torinaブログ

DjangoとBootstrap4で作成したブログ
Python, Django, Kivy, Bootstrap, Apache等のメモです
ソースコード

Kivyで、YesNoなポップアップ

Python Kivy Kivy
約114日前 2016年10月29日14:36
Yes、Noのどちらかをクリックするようなポップアップはよく使います。
今回はKivyで作ってみます。

まずこのような感じ。popup1とpopup2で、それぞれポップアップが開きます。


popup1を押した際のポップアップ


yesを押しと閉じ、上の表示にyes1 clickと表示されます。


こちらはpopup2ボタン


yesで、yes2 clickとなりますね。


Python3.5
Kivy1.9.1
です。

main.py
from kivy.app import App
from kivy.properties import ObjectProperty
from kivy.properties import StringProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.popup import Popup


class YesNoPopUp(BoxLayout):
    """ポップアップのコンテンツ部分

    YesNoPopUp(yes=self.yes1, no=self.no, text='popup1')
    のように使い、Yesボタン、Noボタンと紐づけたい関数を渡し、textには表示したい文字列を渡してください。
    """

    text = StringProperty()
    yes = ObjectProperty(None)
    no = ObjectProperty(None)


class TestLayout(BoxLayout):
    """ルートウィジェット"""

    label = ObjectProperty(None)

    def button1(self):
        content = YesNoPopUp(yes=self.yes1, no=self.no, text='popup1')
        self.popup = Popup(title="popup1", content=content)
        self.popup.open()

    def button2(self):
        content = YesNoPopUp(yes=self.yes2, no=self.no, text='popup2')
        self.popup = Popup(title="popup2", content=content)
        self.popup.open()

    def yes1(self):
        """ポップアップでYesを押された際に呼びたい関数、バージョン1"""

        self.label.text = 'yes1 click'
        self.popup.dismiss()

    def yes2(self):
        """ポップアップでYesを押された際に呼びたい関数、バージョン2"""

        self.label.text = 'yes2 click'
        self.popup.dismiss()

    def no(self):
        """ポップアップでNoを押された際に呼びたい関数。今回は共通して使う"""

        self.label.text = 'no click'
        self.popup.dismiss()


class TestApp(App):

    def build(self):
        return TestLayout()

TestApp().run()


test.kv
<TestLayout>
	label: label
	orientation: 'vertical'

	Label:
		id: label
		text: 'Hello'

	Button:
		text: 'popup1'
		on_release: root.button1()

	Button:
		text: 'popup2'
		on_release: root.button2()


<YesNoPopUp>
	orientation: 'vertical'

	Label:
		size_hint: 1, .9
		text: root.text

	BoxLayout:
		size_hint: 1, .1
		orientation: 'horizontal'

		Button:
			size_hint: .5, 1
			text: 'Yes'
			on_release: root.yes()

		Button:
			size_hint: .5, 1
			text: 'No'
			on_release: root.no()



トップ画面のレイアウトです。今回はそこまで重要でないです。テキスト表示欄と、2種類のボタンがあります。
<TestLayout>
	label: label
	orientation: 'vertical'

	Label:
		id: label
		text: 'Hello'

	Button:
		text: 'popup1'
		on_release: root.button1()

	Button:
		text: 'popup2'
		on_release: root.button2()



こちらが本題の、ポップアップ部分です。
上9割にテキスト、残りにYesとNoのボタンがあります。
押すと、それぞれyes、no関数が呼ばれます。
表示するテキストは、root.textの内容です。
<YesNoPopUp>
	orientation: 'vertical'

	Label:
		size_hint: 1, .9
		text: root.text

	BoxLayout:
		size_hint: 1, .1
		orientation: 'horizontal'

		Button:
			size_hint: .5, 1
			text: 'Yes'
			on_release: root.yes()

		Button:
			size_hint: .5, 1
			text: 'No'
			on_release: root.no()
		



YesNoPopUpクラスです。
textや、Yesボタン、Noボタンで呼ばれる関数等はここに直接定義しません。
PopUpを表示する側でコントロールできるようにしました。
class YesNoPopUp(BoxLayout):
    """ポップアップのコンテンツ部分

    YesNoPopUp(yes=self.yes1, no=self.no, text='popup1')
    のように使い、Yesボタン、Noボタンと紐づけたい関数を渡し、textには表示したい文字列を渡してください。
    """

    text = StringProperty()
    yes = ObjectProperty(None)
    no = ObjectProperty(None)



TestLayoutクラスです。
popup1ボタンでbutton1が、popup2ボタンでbutton2が呼ばれます。kvファイルに書いたとおりです。
class TestLayout(BoxLayout):
    """ルートウィジェット"""

    label = ObjectProperty(None)

    def button1(self):
        content = YesNoPopUp(yes=self.yes1, no=self.no, text='popup1')
        self.popup = Popup(title="popup1", content=content)
        self.popup.open()

    def button2(self):
        content = YesNoPopUp(yes=self.yes2, no=self.no, text='popup2')
        self.popup = Popup(title="popup2", content=content)
        self.popup.open()

    def yes1(self):
        """ポップアップでYesを押された際に呼びたい関数、バージョン1"""

        self.label.text = 'yes1 click'
        self.popup.dismiss()

    def yes2(self):
        """ポップアップでYesを押された際に呼びたい関数、バージョン2"""

        self.label.text = 'yes2 click'
        self.popup.dismiss()

    def no(self):
        """ポップアップでNoを押された際に呼びたい関数。今回は共通して使う"""

        self.label.text = 'no click'
        self.popup.dismiss()


どちらもPopupウィジェットを作成しオープンしてるわけですが、yesやtextに渡しているものが違います。
見た目と土台となる部分をYesNoPopUpクラスとして作成し、呼び出される関数や表示する内容をカスタマイズできるようにしました。
    def button1(self):
        content = YesNoPopUp(yes=self.yes1, no=self.no, text='popup1')
        self.popup = Popup(title="popup1", content=content)
        self.popup.open()

    def button2(self):
        content = YesNoPopUp(yes=self.yes2, no=self.no, text='popup2')
        self.popup = Popup(title="popup2", content=content)
        self.popup.open()


https://kivy.org/docs/api-kivy.uix.popup.html#kivy.uix.popup.Popup
https://gist.github.com/rohman/5300469