[Kivy] Popupの設定① PopupからPopupを呼び出す。

kivy.uix.popupについて

 Popupはモーダル ポップアップを作成するWidgetであり、メッセージやダイアログボックスのようなものを作成するのに使用します。Kivyの公式では、FileChooserのページでpopupを使用してファイルダイアログのようなものを作成する方法を紹介しています。

 紹介されている方法では、メイン画面のクラス内でPopupのコンテンツを定義して、それをPopupに載せています。その時、Popupの閉じるボタンとメイン画面のクラスの関数とを紐付けて、Popupを閉じる処理をメイン画面のクラス内に記述するようにしています。この方法では、メイン画面のクラスの可読性が若干悪くなりますが、Popupを閉じる時に、コンテンツ内のWidgetの値を取得して、メイン画面に反映することが容易にできます。

 今回は、①メイン画面のクラス内でPopupのコンテンツを定義する方法をKv Languageで実施する方法と、②そのPopupに追加したボタンを押すと別のPopup(Kv Languageで作成)が表示されるようにする方法について紹介します。

今回紹介する内容
 ・Popupのクラスの定義(Kv language)
 ・Popupのクラスの定義(Pythonファイル側)
 ・Popupを表示する(コンテンツの定義、Popupへの追加、Popupの表示)
 ・Popupを閉じる
 ・Popup(ダイアログ1)内でPopup(ダイアログ2)を呼び出す

kivy.uix.popupの設定

Popupのクラスの定義(Kv language側)

 Kv languageでPopupのコンテンツを記入する場合、Popupはメイン画面のものと同じファイル内に以下のように別のクラスとして記入します。もう1つのPopup(ダイアログ2)も別クラス<Dialog2>:として記入します。

<Dialog1>:
    BoxLayout:
        size: root.size
        pos: root.pos
        orientation: "vertical"
        spacing: 20

        Button:
            id: d1_button
            text: 'Call Dialog2'
            on_press: root.button_press()

        BoxLayout:
            size_hint_y: None
            height: 30
            Button:
                text: "Cancel"
                on_release: root.cancel()

            Button:
                text: "Ok"
                on_release: root.select()

Popupのクラスの定義(Pythonファイル側)

 Pythonファイルには、Popup(Dialog1, Dialog2)に載せるコンテンツの関数をメイン画面のクラス(PopupTestWidget)内で呼べるようにするために、Kv languageで作成した関数名と同じObjectPropertyを作成します。

# Popupから呼び出されるPopupのクラス(Dialog2)
class Dialog2(FloatLayout):
    select2 = ObjectProperty(None)
    cancel2 = ObjectProperty(None)

# メイン画面から呼び出されるPopupのクラス(Dialog1)
class Dialog1(FloatLayout):
    select = ObjectProperty(None)
    cancel = ObjectProperty(None)
    button_press = ObjectProperty(None)

Popupを表示する(コンテンツの定義、Popupへの追加、Popupの表示)

 Popupを表示するには、まずコンテンツ(Dialog1)を定義します。コンテンツの定義では、関数の紐付け(kvファイル内での関数名とpythonファイル内での関数名を紐付ける)を行っています。

 次に、定義したコンテンツ、Popupのタイトルや表示位置を指定してPopupを定義します。

 最後に、定義したPopupをopen()によって表示します。

    def on_button1_press(self):
        content = Dialog1(
            select=self.select,
            cancel=self.dismiss_popup,
            button_press=self.on_d1_button_press)
        self._popup = Popup(title="Setting1", content=content,
                            size_hint=(0.9, 0.9))
        self._popup.open()

Popupを閉じる(ダイアログ1、ダイアログ2)

 Popupを閉じるのには、dismiss()を使用します。Popup内のボタンの動作は、メイン画面と同じクラス内で定義した関数内に以下のように記入します。

def select(self):
  # ここに、コンテンツ内のWidgetの値を取得する作業などを記入する
    self._popup.dismiss()

def dismiss_popup(self):
    self._popup.dismiss()

Popup(ダイアログ1)内でPopup(ダイアログ2)を呼び出す

 今回は、Popup(ダイアログ1)のButton(id: d1_button)を押した場合に、Popup(ダイアログ2)を表示するため、以下のようにボタンを押した場合に実行する関数on_d1_button_press()内に、①Popup(ダイアログ2のコンテンツとPopupの定義を記入して、②その表示の指示をしています。

 ダイアログ2のコンテンツの定義でも、関数の紐付け(kvファイル内での関数名とpythonファイル内での関数名を紐付ける)をおこなっており、これらの関数はメイン画面のクラスに記入するため、ダイアログ2のコンテンツ内のWidgetの値もメイン画面のクラスで容易に扱うことが可能になっています。

    def on_d1_button_press(self):
        content = Dialog2(
            select2=self.select2, cancel2=self.dismiss_popup2)
        self._popup2 = Popup(
            title="Setting2", content=content,
            size_hint=(0.9, 0.9))
        self._popup2.open()

サンプルプログラム

 下記の2つのファイルを同じフォルダに保存して、プログラムを実行するとメイン画面が表示されます。メイン画面内の’Open Dialog1’ボタンを押すと、ダイアログ1(Popup)が表示されます。ダイアログ1内の’Open Dialog2’ボタンを押すと、ダイアログ2(Popup)が表示されます。
 ダイアログ1、ダイアログ2内の’Chancel’や’Ok’ボタンを押すと、そのダイアログが閉じます。

左上: メイン画面
右上: ダイアログ1(title:Setting1)
左 : ダイアログ2(title:Setting2)

#:kivy 2.0


<PopupTestWidget>:
    BoxLayout:
        size: root.size
        orientation: 'vertical'
        padding: 20
        canvas.before:
            Color:
                rgba: 0.7, 0.7, 0.7, 1
            Rectangle:
                size: self.size
                pos: self.pos

        Button:
            id: button1
            text: 'Open Dialog1'
            on_press: root.on_button1_press()


<Dialog1>:
    BoxLayout:
        size: root.size
        pos: root.pos
        orientation: "vertical"
        spacing: 20

        Button:
            id: d1_button
            text: 'Call Dialog2'
            on_press: root.button_press()

        BoxLayout:
            size_hint_y: None
            height: 30
            Button:
                text: "Cancel"
                on_release: root.cancel()

            Button:
                text: "Ok"
                on_release: root.select()

<Dialog2>:
    BoxLayout:
        size: root.size
        pos: root.pos
        orientation: "vertical"
        spacing: 20

        Label:
            text: 'This is Dialog2'

        BoxLayout:
            size_hint_y: None
            height: 30
            Button:
                text: "Cancel"
                on_release: root.cancel2()

            Button:
                text: "Ok"
                on_release: root.select2()
# -*- coding: utf-8 -*-

import os
import kivy

from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.floatlayout import FloatLayout
from kivy.lang import Builder
from kivy.config import Config
from kivy.properties import ObjectProperty
from kivy.uix.popup import Popup

kivy.require('2.2.0')

# 画面サイズの指定
Config.set('graphics', 'width', '600')
Config.set('graphics', 'height', '500')

Builder.load_file(os.path.dirname(__file__) + "/interface.kv")


class Dialog2(FloatLayout):
    select2 = ObjectProperty(None)
    cancel2 = ObjectProperty(None)


class Dialog1(FloatLayout):
    select = ObjectProperty(None)
    cancel = ObjectProperty(None)
    button_press = ObjectProperty(None)


class PopupTestWidget(Widget):

    def __init__(self, **kwargs):
        super(PopupTestWidget, self).__init__(**kwargs)

    def on_button1_press(self):
        content = Dialog1(
            select=self.select,
            cancel=self.dismiss_popup,
            button_press=self.on_d1_button_press)
        self._popup = Popup(title="Setting1", content=content,
                            size_hint=(0.9, 0.9))
        self._popup.open()

    def on_d1_button_press(self):
        content = Dialog2(
            select2=self.select2, cancel2=self.dismiss_popup2)
        self._popup2 = Popup(
            title="Setting2", content=content,
            size_hint=(0.9, 0.9))
        self._popup2.open()

    def select(self):
        self._popup.dismiss()

    def dismiss_popup(self):
        self._popup.dismiss()

    def select2(self):
        self._popup2.dismiss()

    def dismiss_popup2(self):
        self._popup2.dismiss()


class PopupTestApp(App):
    def __init__(self, **kwargs):
        super(PopupTestApp, self).__init__(**kwargs)
        self.title = 'Popup Test'

    def build(self):
        return PopupTestWidget()


if __name__ == '__main__':
    app = PopupTestApp()
    app.run()
タイトルとURLをコピーしました