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

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

今回は、正解不正解を表示するポップアップとPlayFieldWidgetやQuestionLabel、ButtonsWidgetを使って実際にプレイするレイアウトを作成します。

 

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

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

 

 

 

スポンサードサーチ


正解不正解を表示するポップアップ

正解不正解を表示するポップアップでは、Part16で作成したResultWidgetを追加したり、正解時の文言、不正解時の文言、マルバツどちらかが表示される処理などを設定します。

 

 

コードの提示

正解不正解を表示するポップアップのソースコードを以下に示します。

import kivy
kivy.require("2.0.0")

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.widget import Widget
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.popup import Popup
from kivy.graphics import Color, Rectangle, Ellipse
from kivy.graphics import Rotate
from kivy.graphics import Line
from kivy.graphics.context_instructions import PushMatrix, PopMatrix
from kivy.storage.jsonstore import JsonStore

from kivy.core.window import Window

import numpy as np
import random
import copy

class MatchStickWidget(Widget):
    # 省略

class MatchStickFrameWidget(Widget):
    # 省略

class PlayFieldWidget(FloatLayout):
    # 省略

class QuestionLabel(Label):
    # 省略

class ButtonBaseWidget(Button):
    # 省略

class ButtonsWidget(BoxLayout):
    # 省略

class ResultWidget(Widget):
    # 省略

class ResultPopup(Popup):
    def __init__(self, **kwargs):
        super(ResultPopup, self).__init__(**kwargs)
        self.auto_dismiss = False
        self.background = ""
        self.background_color = [1, 1, 1, 1]
        self.pos_hint = {"center_x":0.5, "center_y":0.5}
        self.separator_height = 0
        self.size_hint = [0.3, 0.4]
        self.wid = ResultWidget(size_hint=[1, 0.4])
        self.lb = Label(bold=True, color=[0, 0, 0, 1], font_size=36, size_hint=[1, 0.3])
        self.btn_ok = ButtonBaseWidget(font_size=15, size_hint=[1, 0.3], text="OK", on_press=self.dismiss)
        self.btn_ok.bold = False
        self.btn_ok.line_rect.width = 2
        self.box = BoxLayout(orientation="vertical")
        self.box.add_widget(self.wid)
        self.box.add_widget(self.lb)
        self.box.add_widget(self.btn_ok)
        self.add_widget(self.box)
        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.lb.text = "Congratulation!!!"
            self.wid.xc.a = 0
            self.wid.cc.a = 1
        else:
            self.lb.text = "Your answer is incorrect..."
            self.wid.cc.a = 0
            self.wid.xc.a = 1

class RootWidget(FloatLayout):
    def __init__(self, **kwargs):
        super(RootWidget, self).__init__(**kwargs)
        with self.canvas.before:
            Color(rgb=[1, 1, 1])
            self.bg_rect = Rectangle(pos=self.pos, size=self.size)
    def on_size(self, *args):
        self.bg_rect.size = self.size

class MatchStickQuizApp(App):
    def build(self):
        root = RootWidget()
        popup = ResultPopup()
        #popup.tof = True
        root.add_widget(popup)
        return root

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

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

  

 

コードの解説

10行目の「import文」は、Popupをインポートしています。

 

 

44行目から74行目の「ResultPopup」は、正解不正解を表示するポップアップです。

 

45行目から65行目の「init関数」は、ResultPopupを初期化しています。

 

46行目の「super関数」は、Popupクラスのinit関数を実行しています。

 

47行目の「self.auto_dismiss」は、範囲外をクリックされたときにポップアップを消す設定を行っています。Falesを代入することでその動作をしないように設定しています。

 

48行目の「self.background」は、背景に入れる画像を設定しています。空の文字列を代入することで、背景に何も画像を入れないという設定をしています。

 

49行目の「self.background_color」は、背景色を設定しています。[1, 1, 1, 1]は白色を表しています。

 

50行目の「self.pos_hint」は、表示位置を比率によって設定しています。{“center_x”:0.5, “center_y”:0.5}は、画面中心に表示するということを表しています。

 

51行目の「self.separator_height」は、ポップアップのタイトルと子ウィジェットの間に表示される線の位置を設定しています。0を代入することで線を非表示にしています。

 

52行目の「self.size_hint」は、ポップアップのサイズを比率によって設定しています。

 

53行目の「self.wid」は、ReusltWidgetを代入する変数です。

 

54行目の「self.lb」は、正解不正解時の文言を表示するLabelを代入する変数です。

 

55行目の「self.btn_ok」は、ポップアップを消すためのButtonBaseWidgetを代入する変数です。

 

56行目の「self.btn_ok.bold」は、Falseを代入することで太字の設定を解除しています。

 

57行目の「self.btn_ok.line_rect.width」は、2を代入することで線の太さを細くしています。

 

58行目の「self.box」は、BoxLayoutを代入する変数です。

 

59行目から61行目の「self.box.add_widget関数」は、それぞれself.wid、self.lb、self.btn_okをself.boxに追加しています。

 

62行目の「add_widget関数」は、self.boxをResultPopupに代入しています。

 

63行目の「create_property関数」は、tofという変数をプロパティとして生成しています。プロパティとすることで、後述するbind関数を使用することができます。

 

tofはTrueかFalseのみを代入します。Trueは正解、Falseは不正解を表します。

 

64行目の「self.on_tof()」は、後述するon_tof関数を実行しています。

 

65行目の「self.bind(tof=self.on_tof)」は、tofという変数が変化したとき述するon_tof関数が実行されるように紐づけています。

 

66行目から74行目の「on_tof関数」は、tofに変化があったとき実行される関数です。

 

67行目の「if文」は、「tofがTrueである」ということを判別する条件式です。tofがTrueであるとき、つまり正解しているとき68行目から70行目が実行されます。

 

68行目では、self.lb.textに「Congratulation!!!」を代入しています。

69行目では、self.wid.xc.aに0を代入することでバツを非表示にしています。

70行目では、self.wid.cc.aに1を代入することでマルを表示しています。

 

71行目の「if文」は、「tofがTrueでない」ということ判別する条件式です。tofがFalseであるとき、つまり不正解であるとき72行目から74行目が実行されます。

 

72行目では、self.lb.textに「Your answer is incorrect…」を代入しています。

73行目では、self.wid.cc.aに0を代入することでマルを非表示にしています。

74行目では、self.wid.xc.aに1を代入することでバツを表示しています。

 

 

動作確認

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

python matchstickquiz.py

 

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

 

 

スポンサードサーチ


プレイ画面

プレイ画面のレイアウトを以下に示します。このレイアウトには、PlayFieldWidgetやQuestionLabel、ButtonsWidgetを以下のように配置します。

*python_matchstickquiz_part17_explain01.jpg

 

また、「答える」ボタンを押されたときの処理を作成します。

 

 

コードの提示

実際にプレイする画面のレイアウトのソースコードを以下に示します。

import kivy
kivy.require("2.0.0")

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.widget import Widget
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.popup import Popup
from kivy.graphics import Color, Rectangle, Ellipse
from kivy.graphics import Rotate
from kivy.graphics import Line
from kivy.graphics.context_instructions import PushMatrix, PopMatrix
from kivy.storage.jsonstore import JsonStore

from kivy.core.window import Window

import numpy as np
import random
import copy

class MatchStickWidget(Widget):
    # 省略

class MatchStickFrameWidget(Widget):
    # 省略

class PlayFieldWidget(FloatLayout):
    # 省略

class QuestionLabel(Label):
    # 省略

class ButtonBaseWidget(Button):
    # 省略

class ButtonsWidget(BoxLayout):
    # 省略

class ResultWidget(Widget):
    # 省略

class ResultPopup(Popup):
    # 省略

class PlayWidget(BoxLayout):
    def __init__(self, **kwargs):
        super(PlayWidget, self).__init__(**kwargs)
        self.orientation = "horizontal"
        self.boxQA = BoxLayout(orientation="vertical", size_hint=[0.75, 1])
        self.qlb = QuestionLabel(size_hint=[1, 0.3])
        self.pfw = PlayFieldWidget(size_hint=[1, 0.7])
        self.boxQA.add_widget(self.qlb)
        self.boxQA.add_widget(self.pfw)
        self.btnswid = ButtonsWidget(size_hint=[0.25, 1])
        self.add_widget(self.boxQA)
        self.add_widget(self.btnswid)
        self.resultpopup = ResultPopup()
    def on_press_btn_answer(self, *args):
        self.resultpopup.tof = self.pfw.checkAnswerFML()
        self.resultpopup.open()

class RootWidget(FloatLayout):
    def __init__(self, **kwargs):
        super(RootWidget, self).__init__(**kwargs)
        with self.canvas.before:
            Color(rgb=[1, 1, 1])
            self.bg_rect = Rectangle(pos=self.pos, size=self.size)
    def on_size(self, *args):
        self.bg_rect.size = self.size

class MatchStickQuizApp(App):
    def build(self):
        root = RootWidget()
        pw = PlayWidget()
        root.add_widget(pw)
        return root

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

 

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

  

 

コードの解説

47行目から62行目の「PlayWidget」は、実際にプレイする画面のレイアウトです。

 

48行目から59行目の「init関数」は、PlayWidgetを初期化しています。

 

49行目の「super関数」は、BoxLayoutのinit関数を実行しています。

 

50行目の「self.orientation」は、子ウィジェットを追加する方向を設定します。「horizontal」を代入しているため、水平方向に子ウィジェットは追加されていきます。

 

51行目の「self.boxQA」は、先程の画像における左側のレイアウトを設定するための変数です。

 

52行目の「self.qlb」は、QuestionLabelが代入される変数です。

 

53行目の「self.pfw」は、PlayFieldWidgetが代入される変数です。

  

54行目と55行目の「self.boxQA.add_widget関数」は、それぞれself.qlbとself.pfwをself.boxQAに追加しています。

 

56行目の「self.btnswid」は、ButtonsWidgetが代入される変数です。

 

57行目と58行目の「self.add_widget関数」は、それぞれself.boxQAとself.btnswidをPlayWidgetに追加しています。

 

59行目の「self.resultpopup」は、ResultPopupが代入される変数です。

 

60行目から62行目の「on_press_btn_answer関数」は、「答える」ボタンが押されたときに実行させる関数です。

 

61行目では、self.pfw.checkAnswerFML関数の結果をself.resultpopup.tofに代入しています。

 

62行目では、ResultPopupを表示させています。

 

 

動作確認

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

python matchstickquiz.py

 

以下のように表示されれば動作確認は完了です。今は、問題を設定していないためマッチ棒は表示されず、マッチ棒枠のみが表示されています。

 

 

スポンサードサーチ


まとめ

今回はポップアップとプレイ画面のレイアウトを作成しました。

ポップアップは、実際に動かしてみたいとどのように動作するか分からないと思いますので、今は理解できていなくても問題ありません。

プレイ画面のレイアウトは作成してきたものを追加していくだけでしたので、理解しやすかったと思います。

 

次回Part18では、タイトル画面のレイアウトと元のレイアウトを作成します。次回でマッチ棒クイズは完成となります。

 

 

 

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


スポンサードサーチ