【Python】マッチ棒クイズ開発 Part21

こんにちは、にわこまです。

今回は、プレイ画面の右側に表示するボタンの親クラスとポップアップを作成します。ポップアップの作成では、ResultWidgetとResultPopupを統合させましたのでお楽しみください。

 

誤字脱字や分からない点がございましたらご連絡お願いいたします!

メールまたはTwitterのDMまで!!

 

 

 

スポンサードサーチ


ボタンの親クラス

ここではボタンの親クラスを作成します。つまりButtonBaseWidgetを作成します。

ButtonBaseWidgetはもともとコード量が少なかったですが、kvファイルを使用することでpythonファイルに記述するコード量がさらに減りました。

また、ボタン上にマウスがあるときに実行する関数の名前を変更しています。

 

 

コードの提示

kvファイルでボタンの親クラスを表現するソースコードを以下に示します。

# -*- coding: utf-8 -*-
#:import np numpy

<MatchStickWidget>:
    # 省略

<MatchStickFrameWidget>:
    # 省略

<PlayFieldWidget>:
    # 省略

<ButtonBaseWidget>:
    background_color: [1, 1, 1, 1]
    background_normal: ""
    bold: True
    color: [0, 0, 0, 1]
    font_size: 36
    size_hint: [1, 0.25]
    canvas.before:
        Color:
            rgb: [0, 0, 0]
        Line:
            width: 5
            rectangle: [self.x, self.y, self.width, self.height]


<RootWidget>:
    canvas:
        Color:
            rgb: [1, 1, 1]
        Rectangle:
            pos: self.pos
            size: self.size

 

pythonファイルでボタンの親クラスを表現するソースコードを以下に示します。

import kivy
kivy.require('2.0.0')

from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.widget import Widget
from kivy.uix.button import Button
from kivy.storage.jsonstore import JsonStore

from kivy.core.window import Window

from kivy.lang import Builder
Builder.load_file('matchstickquiz_V2101.kv')

import numpy as np
import random
import copy

class MatchStickWidget(Widget):
    # 省略

class MatchStickFrameWidget(Widget):
    # 省略

class PlayFieldWidget(FloatLayout):
    # 省略

class ButtonBaseWidget(Button):
    def __init__(self, **kwargs):
        super(ButtonBaseWidget, self).__init__(**kwargs)
        Window.bind(mouse_pos=self.on_hover)
    def on_hover(self, *args):
        if(self.x <= args[1][0] and args[1][0] <=self.x+self.width
            and self.y <= args[1][1] and args[1][1] <= self.y+self.height):
            self.background_color = [0, 0, 0, 1]
            self.color = [1, 1, 1, 1]
        else:
            self.background_color = [1, 1, 1, 1]
            self.color = [0, 0, 0, 1]

class RootWidget(FloatLayout):
    pass


class MatchStickQuizApp(App):
    def build(self):
        root = RootWidget()
        bbw = ButtonBaseWidget(text="Test Button", pos_hint={"center_y":0.5})
        root.add_widget(bbw)
        return root


if __name__ == '__main__':
    MatchStickQuizApp().run()
    pass

  

上記のコードは以下からダウンロードできます。

 

 

コードの解説 kvファイル

13行目から25行目の「ButtonsBaseWidget」は、プレイ画面の右側に表示するボタンの親クラスです。

 

14行目の「background_color」は、ボタンの背景の色を保持する変数です。[1, 1, 1]は白色を表します。

 

15行目の「background_normal」は、ボタンの背景に表示する画像のパスを保持する変数です。空の文字列を代入することで画像を指定しないという設定にしています。

 

16行目の「bold」は、文字の太さを指定する変数です。Trueを代入することで太字に設定しています。

 

17行目の「color」は、文字の色を設定する変数です。[0, 0, 0, 1]は黒色を表します。

 

18行目の「font_size」は、文字のサイズを設定する変数です。36を代入しています。

 

19行目の「size_hint」は、ボタンのサイズを比率によって設定する変数です。横幅は100%、縦幅は25%に設定しています。

 

20行目の「canvas.before」は、canvas.beforeオブジェクトを宣言しています。この宣言以降でインデントを1つ下げるとcanvas.beforeへ追加するという扱いになります。

 

21行目の「Color」は、後述するLineの色を設定するオブジェクトです。

22行目では、色を黒色に設定しています。

 

23行目の「Line」は、ボタンを囲むためのオブジェクトです。

24行目の「width」は、線の太さを保持する変数です。5を代入しています。

25行目の「rectangle」は、線を長方形に表示するための座標を保持する変数です。

 

 

コードの解説 pythonファイル

pythonに書かれているコードは、ほとんどこれまでのPartで解説しているため、新しく記述したコードや気を付けて欲しいコードについて解説します。

 

ButtonBaseWidgetクラスは「on_mouse_pos」と表現していた関数を「on_hover」という表現に変更しました。

名称が変わっただけであるため、処理などの変更はありません。

 

 

動作確認

コードを保存したら、コマンドプロンプトを開きファイルを保存したフォルダまで移動します。移動したら、以下のコマンドを入力し実行します。

python matchstickquiz.py

 

マウスがボタン上にないとき以下のように表示されていることを確認します。

 

マウスがボタン上にあるとき以下のように表示されいることを確認します。

 

 

スポンサードサーチ


ポップアップ

正解か不正解かをポップアップによって表示するためのものです。

表示するのはマルかバツの図形と「正解です」または「不正解です」の意の文字列です。

 

冒頭でも書きましたが、今まではResultWidgetとReusltPopupを用いてポップアップを表現していましたが、今回は統合して1つのオブジェクトとします。

 

 

コードの提示

kvファイルでResultPopupを表現するソースコードを以下に示します。

# -*- coding: utf-8 -*-
#:import np numpy

<MatchStickWidget>:
    # 省略

<MatchStickFrameWidget>:
    # 省略

<PlayFieldWidget>:
    # 省略

<ButtonBaseWidget>:
    # 省略

<ResultPopup>:
    auto_dismiss: False
    background: ""
    background_color: [1, 1, 1, 1]
    pos_hint: {"center_x":0.5, "center_y":0.5}
    separator_height: 0
    size_hint: [0.3, 0.4]
    tof: False
    BoxLayout:
        orientation: "vertical"
        Widget:
            id: wid
            size_hint: [1, 0.4]
            half_y: int(self.height / 2)
            canvas.before:
                Color:
                    group: "cc"
                    rgb: [0.86, 0.08, 0.23]
                Line:
                    width: 7
                    circle: [self.center_x, self.center_y, self.half_y]
                Color:
                    group: "xc"
                    rgb: [0, 0, 1]
                Line:
                    cap: "none"
                    width: 7
                    points: [self.center_x-int(self.height/2), self.y, self.center_x+int(self.height/2), self.y+self.height]
                Line:
                    cap: "none"
                    width: 7
                    points: [self.center_x-int(self.height/2), self.center_y+int(self.height/2), self.center_x+int(self.height/2), self.center_y-int(self.height/2)]
        Label:
            id: lb
            bold: True
            color: [0, 0, 0, 1]
            font_size: 36
            size_hint: [1, 0.3]
        ButtonBaseWidget:
            bold: False
            font_size: 36
            size_hint: [1, 0.3]
            text: "OK"
            on_press: root.dismiss()


<RootWidget>:
    canvas:
        Color:
            rgb: [1, 1, 1]
        Rectangle:
            pos: self.pos
            size: self.size

 

pythonファイルでResultPopupを表現するソースコードを以下に示します。

import kivy
kivy.require('2.0.0')

from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.widget import Widget
from kivy.uix.button import Button
from kivy.storage.jsonstore import JsonStore

from kivy.core.window import Window

from kivy.lang import Builder
Builder.load_file('matchstickquiz_V2101.kv')

import numpy as np
import random
import copy

class MatchStickWidget(Widget):
    # 省略

class MatchStickFrameWidget(Widget):
    # 省略

class PlayFieldWidget(FloatLayout):
    # 省略

class ButtonBaseWidget(Button):
    # 省略

class ResultPopup(Popup):
    def __init__(self, **kwargs):
        super(ResultPopup, self).__init__(**kwargs)
        self.create_property("tof", value=False, default_value=False)
        self.on_tof()
        self.bind(tof=self.on_tof)
    def on_tof(self, *args):
        if(self.tof):
            self.ids["lb"].text = "Congratulation!!!"
            self.ids["wid"].canvas.before.get_group("xc")[0].a = 0
            self.ids["wid"].canvas.before.get_group("cc")[0].a = 1
        else:
            self.ids["lb"].text = "Your answer is incorrect..."
            self.ids["wid"].canvas.before.get_group("cc")[0].a = 0
            self.ids["wid"].canvas.before.get_group("xc")[0].a = 1

class RootWidget(FloatLayout):
    pass


class MatchStickQuizApp(App):
    def build(self):
        root = RootWidget()
        bbw = ButtonBaseWidget(text="Test Button", pos_hint={"center_y":0.5})
        root.add_widget(bbw)
        return root


if __name__ == '__main__':
    MatchStickQuizApp().run()
    pass

 

上記のコードは以下からダウンロードできます。

 

 

コードの解説 kvファイル

16行目から59行目の「ReusltPopup」は、正解不正解を表示するポップアップです。

 

17行目の「auto_dismiss」は、ポップアップ以外の場所をクリックしたときにポップアップを閉じるかどうかを設定する変数です。Falseを代入することで閉じないように設定しています。

 

18行目の「background」は、ポップアップの背景に表示する画像のパスを保持する変数です。空の文字列を代入することで何も表示しないという設定にしています。

 

19行目の「background_color」は、ポップアップの背景色を保持する変数です。[1, 1, 1, 1]は白色を表しています。

 

20行目の「pos_hint」は、比率によって表示位置を設定する変数です。画面の中心に表示されるように設定しています。

 

21行目の「separator_height」は、タイトルとコンテンツの間に表示される線の高さを保持する変数です。0を代入することで線を表示しないように設定しています。

 

22行目の「size_hint」は、比率によってサイズを設定する変数です。横幅が30%、縦幅が40%になるように設定しています。

 

23行目の「tof」は、正解か不正解を保持する変数です。初期値としてFalseが代入されています。Trueが正解、Falseが不正解を表しています。

 

24行目の「BoxLayout」は、BoxLayoutオブジェクトを宣言しています。この宣言以降でインデントを1つ下げるとBoxLayoutへ追加するという扱いになります。

 

25行目の「orientation」は、BoxLayoutをドの方向に追加していくかを設定する変数です。verticalを代入することで縦方向に追加すると設定しています。

 

 

26行目の「Widget」は、マルとバツを表示するオブジェクトです。BoxLayoutに追加しています。

 

27行目の「id」は、そのオブジェクトを識別するための変数です。つまり、クラス名を定義するようなものです。widを代入することでWidgetオブジェクトをwidとして呼び出すことができます。

 

28行目の「size_hint」は、比率によってWidgetのサイズを設定する変数です。横幅100%、縦幅40%に設定しています。

 

29行目の「half_y」は、Widgetの高さの半分を代入する変数です。後述するマルやバツの図形を中心に表示するために使用します。

 

30行目の「canvas.before」は、canvas.beforeオブジェクトを宣言しています。この宣言以降でインデントを1つ下げるとcanvas.beforeへ追加するという扱いになります。

 

31行目の「Color」は、後述するLineの色を設定するオブジェクトです。

32行目の「group: ‘cc’」は、Lineオブジェクトにccグループという属性を付与しています。pythonファイル側からLineオブジェクトを呼び出す時に使用します。

33行目では、色を赤色に設定しています。

 

34行目の「Line」は、マルを表現するためのオブジェクトです。

35行目の「width」は、線の太さを保持する変数です。7を代入しています。

36行目の「circle」は、線を円形に表示するための座標を保持する変数です。

 

37行目の「Color」は、後述するLineの色を設定するオブジェクトです。

38行目の「group: ‘xc’」は、Lineオブジェクトにxcグループという属性を付与しています。pythonファイル側からLineオブジェクトを呼び出す時に使用します。

39行目では、色を青色に設定しています。

 

40行目の「Line」と44行目の「Line」は、バツを表現するためのオブジェクトです。

42行目の「width」と46行目の「width」は、線の太さを保持する変数です。7を代入しています。

43行目の「points」と47行目の「points」は、線を直線に表示するための座標を保持する変数です。

 

 

48行目から53行目の「Label」は、文言を表示するオブジェクトです。BoxLayoutに追加しています。

 

49行目の「id」は、そのオブジェクトを識別するための変数です。つまり、クラス名を定義するようなものです。lbを代入することでLabelオブジェクトをlbとして呼び出すことができます。

 

50行目の「bold」は、文字の太さを設定する変数です。Trueを代入するうことで太字に設定しています。

 

51行目の「color」は、文字の色を設定する変数です。[0, 0, 0, 1]は黒色を表しています。

 

52行目の「font_size」は、文字の大きさを設定する変数です。36を代入しています。

 

53行目の「size_hint」は、比率によってサイズを設定しています。横幅を100%、縦幅を30%に設定しています。

 

 

54行目から59行目の「ButtonsBaseWidget」は、ポップアップを閉じるためのボタンです。

 

55行目の「bold」は、文字の太さを設定する変数です。Falseを代入することで太字ではなくしています。

 

56行目の「font_size」は、文字の大きさを保持する変数です。36を代入しています。

 

57行目の「size_hint」は、比率によってサイズを設定しています。横幅を100%、縦幅を30%に設定しています。

 

58行目の「text」は、ボタンに表示する文字列を保持する変数です。OKを代入しています。

  

59行目の「on_press」は、ボタンがクリックされたときに実行される関数です。「root.dismiss()」を定義することで、クリックされたらポップアップを閉じるようにしています。

 

 

コードの解説 pythonファイル

pythonに書かれているコードは、ほとんどこれまでのPartで解説しているため、新しく記述したコードや気を付けて欲しいコードについて解説します。

 

39行目と43行目では、Labelオブジェクトのテキストを「self.ids[“lb”].text」で呼び出しています。「self.ids[“lb”]」によって、idがlbのオブジェクトを指定しています。

 

40行目と45行では、バツのColorオブジェクトの透明度を「self.ids[“wid”].canvas.before.get_group(“xc”)[0].a」で呼び出しています。

self.ids[“wid”]」によって、idがwidのオブジェクトを指定しています。

さらに「canvas.before.get_group(“xc”)[0]」によって、groupがxcのオブジェクトたちから0番目のオブジェクトを指定しています。

  

41行目と44行目では、マルのColorオブジェクトの透明度を「self.ids[“wid”].canvas.before.get_group(“cc”)[0].a」で呼び出しています。

self.ids[“wid”]」によって、idがwidのオブジェクトを指定しています。

さらに「canvas.before.get_group(“cc”)[0]」によって、groupがccのオブジェクトたちから0番目のオブジェクトを指定しています。

  

 

動作確認

コードを保存したら、コマンドプロンプトを開きファイルを保存したフォルダまで移動します。移動したら、以下のコマンドを入力し実行します。

python matchstickquiz.py

 

以下のように表示されれば動作確認は完了です。マルの動作確認をするときは、MatchStickQuizAppのコメントアウトをコードにすることで確認できます。

 

 

スポンサードサーチ


まとめ

今回は、プレイ画面の右側に表示するボタンの親クラスとポップアップを作成しました。

ポップアップはResultWidgetとResultPopupを統合したため、kvファイルのコードが少し複雑になりました。

基本的にはインデントを1つ下げるとそのオブジェクトに追加するという意味になるので覚えておいてください!

 

次回Part22では、プレイ画面を作成します。つまり、PlayWidgetクラスを作成します。

 

 

 

最後までお読みいただきありがとうございます。


スポンサードサーチ