PyQt5 を使ってひらがなドリルを作ってみた

f:id:touch-sp:20200823123357p:plain:w400
子供のためのひらがなドリルを作ってみた。

はじめに

ひらがなが書かれたテキストファイルを準備する。

あいうえお
ぁぃぅぇぉ
かきくけこ
がぎぐげご
さしすせそ
ざじずぜぞ
たちつてと
っ
だぢづでど
なにぬねの
はひふへほ
ばびぶべぼ
ぱぴぷぺぽ
まみむめも
やゆよ
ゃゅょ
らりるれろ
わをん
ー

その他に音声ファイル、画像ファイルを準備する必要あり。
音声ファイルは「ピンポン」と「ブー」と「無音」(dummy.wav)の三つ。
なぜか一番最初の再生時にうまく音が出ないので「無音」ファイルを再生するようにしている。
画像ファイルは画像の名前をそのままファイル名にする。

Pythonスクリプト

import os
import glob
import random

import sys
from PyQt5 import QtCore
from PyQt5.QtWidgets import QLabel, QApplication, QWidget, QFrame
from PyQt5.QtGui import QImage, QPixmap, QFont

import vlc

with open('kana.txt', encoding='utf-8') as f:
    all_kanas = set(f.read().replace('\n',''))

for i in range(4):
    button_image = [QImage('button/%d.png'%i) for i in range(4)]

ok_sound = vlc.Media('sound/ok.wav')
boo_sound = vlc.Media('sound/boo.wav')
player = vlc.MediaPlayer()

dummy_sound = vlc.Media('sound/dummy.wav')
player.set_media(dummy_sound)
player.play()

os.chdir(os.path.join(os.getcwd(), 'character'))
all_character = [os.path.splitext(i)[0] for i in glob.glob('*.png')]

push_button = [QtCore.Qt.Key_A, QtCore.Qt.Key_S, QtCore.Qt.Key_D, QtCore.Qt.Key_F]
class Window(QWidget):
    def __init__(self):
        super().__init__()
        self.answer_position = 0
        self.button_ready = False
        self.initUI()
        
    def initUI(self):

        self.kana_label = [QLabel(self) for i in range(10)]
        for i in range(10):
            self.kana_label[i].setGeometry(600+i*100, 200, 100, 100)       
            self.kana_label[i].setFont(QFont("Times", 72, QFont.Bold))
            self.kana_label[i].setAlignment(QtCore.Qt.AlignCenter)
            self.kana_label[i].setLineWidth(3)
        
        self.button_label = [QLabel(self) for i in range(4)]
        self.choice_label = [QLabel(self) for i in range(4)]
        for i in range(4):
            self.button_label[i].setGeometry(184 + 434 * i, 900, 250, 50)
            self.button_label[i].setPixmap(QPixmap.fromImage(button_image[i]))

            self.choice_label[i].setGeometry(184 + 434 * i, 650, 250, 250)
            self.choice_label[i].setFont(QFont("Times", 120, QFont.Bold))
            self.choice_label[i].setAlignment(QtCore.Qt.AlignCenter)

        self.pic_label = QLabel(self)
        self.pic_label.setGeometry(50, 50, 500, 500)

        self.make_question()

    def make_question(self):
        #画面のリセット
        for i in range(10):
            self.kana_label[i].setFrameStyle(QFrame.NoFrame)
            self.kana_label[i].setText('')
        character_name = random.choice(all_character)
        star_image = QImage(character_name + '.png')
        self.pic_label.setPixmap(QPixmap.fromImage(star_image))
        kanas = list(character_name)
        kana_len = len(kanas)
        question_position = random.randint(0, kana_len-1)
        question_kana = character_name[question_position]
        kanas[question_position] = ''

        for i in range(kana_len):
            self.kana_label[i].setText(kanas[i])
            
        self.kana_label[question_position].setFrameStyle(QFrame.Box | QFrame.Plain)
        others = list(all_kanas - set([question_kana]))
        choices = random.sample(others, 3)
        choices.append(question_kana) 
        random.shuffle(choices)
        self.answer_position = choices.index(question_kana)

        for i in range(4):
            self.choice_label[i].setText(choices[i])
        
        self.button_ready = True

    def keyPressEvent(self, e):

        if ((e.key() in push_button) and self.button_ready == True):
            
            self.button_ready = False

            if push_button.index(e.key())  == self.answer_position:

                player.set_media(ok_sound)
                player.play()

                loop = QtCore.QEventLoop()
                QtCore.QTimer.singleShot(1000, loop.quit)
                loop.exec_()

                self.make_question()

            else:
                player.set_media(boo_sound)
                player.play()

                loop = QtCore.QEventLoop()
                QtCore.QTimer.singleShot(1000, loop.quit)
                loop.exec_()

                self.button_ready = True
            
        # エスケープキーを押すと画面が閉じる
        if e.key() == QtCore.Qt.Key_Escape:
            self.close()

app = QApplication(sys.argv)
ex =Window()
p = ex.palette()
p.setColor(ex.backgroundRole(), QtCore.Qt.white)
ex.setPalette(p)
ex.showFullScreen()
sys.exit(app.exec_())