Доброе утро али день, мой дорогой друг!
Через несколько дней наступит долгожданная и ненавистная пора школьных занятий и миллионы юных и сонных неучей устремятся в школы за знаниями.
Там их будут мучить домашними заданиями, тестами и прочими контрольными.
А самые юные из них начнут свое знакомство с НЕЙ - великой и ужасной - Таблицей Умножения!
Конечно, родители дома будут продолжать мучить несчастных, неожиданно задавая вопрос посреди разговора: "семь умножить на восемь, быстро??", от чего становится еще тоскливее и печальнее...
Вот было бы классно, если можно выучить таблицу умножения с другом. Причем, с таким другом, который, конечно, круче самих родителей... Например, с Бэтменом!
А у меня и телефончик его завалялся=)
Эй, Рыцарь Ночи, помоги выучить таблицу умножения, будь другом!
Цель
Через несколько дней наступит долгожданная и ненавистная пора школьных занятий и миллионы юных и сонных неучей устремятся в школы за знаниями.
Там их будут мучить домашними заданиями, тестами и прочими контрольными.
А самые юные из них начнут свое знакомство с НЕЙ - великой и ужасной - Таблицей Умножения!
Конечно, родители дома будут продолжать мучить несчастных, неожиданно задавая вопрос посреди разговора: "семь умножить на восемь, быстро??", от чего становится еще тоскливее и печальнее...
Вот было бы классно, если можно выучить таблицу умножения с другом. Причем, с таким другом, который, конечно, круче самих родителей... Например, с Бэтменом!
А у меня и телефончик его завалялся=)
Эй, Рыцарь Ночи, помоги выучить таблицу умножения, будь другом!
Цель
Итак, сегодня мы с помощью программирования совершим маленькое чудо, и напишем программу для изучения таблицы умножения для юных страдальцев.
Программа должна иметь графический интерфейс, иметь визуальную стилистику Темного Рыцаря, говорить голосом Бэтмена. Казалось бы, такая классная программа нужна и важна сама по себе, но нет, возьмем планку выше - она еще должна случайным образом задавать вопросы, типа "2x2=?" и проверять ответы.
Начнем с главного вопроса: чем будем рисовать окошки?
Конечно моей первой мыслью, как программиста на Java, было Swing, но...
От мысли, что нужно писать детскую веселую программку на могучем и грозном языке Enterprise разработки, повеяло холодком и я отложил эту мысль подальше.
Что же еще умеет рисовать красивые окошки?
Причем хотелось бы именно рисовать, не утруждая себя написанием кода, который задает местоположение кнопочек в окне.
И тут я вспомнил про Qt. Великий и прекрасный Qt!
С помощью Qt можно нарисовать любые, самые фантастические окошки. Существует QtCreator и QtDesigner для таких лентяев как я, которые хотят просто набросать кнопочек на поле - и все готово.
Но есть один ужасный минус - чтобы использовать Qt, нужно писать на C++.
А от мысли, что нужно писать детскую веселую программку на C++, повеяло таким морозом, что я, как Эддард Старк, забормотал: "Зима близко..."
И все-таки Qt мне нравится, можно ли как-то обойтись без C++?
Оказалось, можно!
Qt for Python
А не написать ли мне все на Python? А что, мне это нравится))
Сочетание простого лаконичного синтаксиса Python и мощь графической библиотеки Qt - это однозначно круто!
Разработчики Qt, видимо, тоже так думали, когда создавали Qt for Python, официальную библиотеку на Python для работы с Qt.
Спасибо им за это огромное от лица всех школьников, еще не выучивших таблицу умножения!
Инструменты
Итак, для создания нашей чудо-программы, мы будем использовать:
- Python v3.7.3;
- Jetbrans PyCharm в качестве IDE;
- QtDesigner v5.11.1 в качестве рисовалки окошек;
- Горячий шоколад, для придания себе отличного настроения!
Теперь, когда мы во всеоружии - поехали!
Рисуем окошко
Итак, скачиваем QtDesigner, запускаем его. Он сразу предлагает создать форму, выбираем вариант Main Window.
Форма нашей программы очень простая и содержит всего 4 элемента:
- Картинка с Бэтменом (QLabel);
- Надпись с вопросом, типа 2x2 (QLabel);
- Поле вводе ответа (QTextEdit);
- Кнопка проверки ответа (QPushButton).
Все эти элементы управления нашел в списке виджетов, перетащил мышкой на формочку и подогнал по размеру.
Единственный неожиданный для меня момент оказался связан с тем, что картинка на формочке - это тоже QLabel, ну то есть надпись.
Но не будем формалистами, работает и ладно.
Получилось что-то такое:
Нажатием клавиш Ctrl+R можно запустить окошко и посмотреть его в режиме предпросмотра. Удобно.
С рисованием закончено, сохраняем форму в виде файла main.ui вместе с картинкой Бэтмена и иконкой стрелки повтора для кнопки в одну папку.
Не спорьте с PyCharm и соглашайтесь, она знает, что делает=)
Теперь, когда все нужные библиотеки установлены, нужно загрузить формочку, нарисованную в QtCreator.
Это делается всего одной строчкой:
Создадим собственный класс BatTestForm, который будет наследоваться от класса Form и содержать логику игры
И вот так эта красота выглядит в работающем виде:battest
├── batman.png
├── refresh.png
└── main.ui
Содержимое файла main.ui выглядит примерно так:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>722</width>
<height>405</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<widget class="QLabel" name="batman">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>431</width>
<height>371</height>
</rect>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap>back.png</pixmap>
</property>
</widget>
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>440</x>
<y>10</y>
<width>271</width>
<height>51</height>
</rect>
</property>
<property name="font">
<font>
<pointsize>30</pointsize>
</font>
</property>
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
<widget class="QTextEdit" name="result">
<property name="geometry">
<rect>
<x>440</x>
<y>90</y>
<width>271</width>
<height>71</height>
</rect>
</property>
<property name="font">
<font>
<pointsize>30</pointsize>
</font>
</property>
<property name="acceptRichText">
<bool>true</bool>
</property>
</widget>
<widget class="QPushButton" name="refresh">
<property name="geometry">
<rect>
<x>444</x>
<y>172</y>
<width>271</width>
<height>181</height>
</rect>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset>
<normaloff>refresh.png</normaloff>refresh.png</iconset>
</property>
<property name="iconSize">
<size>
<width>128</width>
<height>128</height>
</size>
</property>
</widget>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>722</width>
<height>21</height>
</rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections/>
</ui>
Теперь нужно написать немного кода на Python, чтобы придать этой красоте немного жизни))
Пишем код
Создаем в нашей папочке battest файл main.py, который будет содержать весь код нашей программы.
Для начала, нам нужно импортировать все необходимые библиотеки:
#Доступ к функциям операционной системы
import sys
#Генератор случайных чисел
import random
#Для работы с аудио
from playsound import playsound
#Загрузчик формочек от QtCreator
from PyQt5 import uic
#Классики для работы с Qt
from PyQt5.QtWidgets import QApplication, QMessageBox, QErrorMessage
Это все библиотеки, которые нам понадобятся. Если каких-то библиотек не окажется на вашем компьютере, то PyCharm любезно спросит нас, не хотим ли мы их установить.Не спорьте с PyCharm и соглашайтесь, она знает, что делает=)
Теперь, когда все нужные библиотеки установлены, нужно загрузить формочку, нарисованную в QtCreator.
Это делается всего одной строчкой:
#Загружаем формочку, нарисованную в QtCreator
Form, Window = uic.loadUiType("main.ui")
В результате загрузки формы у нас есть два класса Form и Window, которые мы используем для отображения нарисованной формочки.Создадим собственный класс BatTestForm, который будет наследоваться от класса Form и содержать логику игры
# Класс формы с логикой
class BatTestForm(Form):
# Конструктор получает на вход переменную total - количество вопросов, на которые должен ответить ребенок
def __init__(self, total):
# Вызываем конструктор родителя
super().__init__()
# x - первый множитель
self.x = 0
# y - второй множитель
self.y = 0
# score - число ответов ребеонка
self.score = 0
# total - количество правильных ответов, на которые должен ответить ребенок
self.total = total
# Метод повторной генерации множителей
def update(self):
# x - случайное целое число от 1 до 9
self.x = random.randint(1, 9)
# y - случайное целое число от 1 до 9
self.y = random.randint(1, 9)
# Отображаем надпись на формочке, типа x x y =
self.label.setText(f"{self.x} x {self.y} = ")
# обработчик нажатия кнопки
def check(self):
# z - ответ, введенныйв поле
z = int(self.result.toPlainText().strip())
# Если ответ правильный
if z == self.x * self.y:
# увеличиваем счетчик правильных ответов
self.score += 1
# Играем победную мелодию
playsound("ok.wav", False)
# Если можно продолжать игру дальше
if self.score < self.total:
# Диалоговое окошко показывает, что ответ правильный
msg = QMessageBox()
# Значок информационного окошка
msg.setIcon(QMessageBox.Information)
# Хвалим игррока=)
msg.setText("Ты молодец!")
# Хвалим еще сильнее!
msg.setWindowTitle("Отлично!")
# Диалоговое окошко имеет только кнопку OK
msg.setStandardButtons(QMessageBox.Ok)
# Показываем диалоговое окошко
msg.exec_()
# Очищаем поле ввода
self.result.setText("")
# Ставим курсов в поле ввода
self.result.setFocus()
# Генерируем следующий вопрос
self.update()
# Если конец игры (кончились попытки)
else:
# Диалоговое окошко сообщает о конце игры
msg = QMessageBox()
# Значок окошка с вопросом
msg.setIcon(QMessageBox.Question)
# Спрашиваем, будет ли игрок продолжать?
msg.setText("Еще одну битву?")
# Заголовок окошка
msg.setWindowTitle("Конец битвы!")
# Добавляем кнопки Ok и Cancel диалоговому окошку
msg.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel)
# Отображаем окошко и сохраняем ответ пользователя
res = msg.exec_()
# Если игрок нажал Ok - обнуляем счетчик попыток и начинаем заново
if res == QMessageBox.Ok:
self.score = 0
self.result.setText("")
self.result.setFocus()
self.update()
else:
# Если игрок нажал Cancel - завершаем программу
sys.exit(0)
# Если ответ неправильный
else:
# Играем мелодию проигрыша
playsound("error.wav", False)
# Создаем окно ошибки
m = QErrorMessage()
# Текcт ошибки
m.showMessage("Неправильно((( Давай еще разок")
# Показываем ошибку
m.exec_()
Из-за обилия комментариев код кажется длинным, но на самом деле все довольно просто.
Обрабатываются 3 ситуации:
- Игрок ответил правильно;
- Игрок ответил неправильно;
- Конец игры.
Для нового вопроса есть метод update, который генерирует случайные множители.
Для обработки ответа есть метод check, который проверяет ответ и реагирует в зависимости от результата.
Осталось совсем немного: запустить приложение
# Объект Qt приложения
application = QApplication([])
# Главное окно
window = Window()
# Форма в главном окне
form = BatTestForm(10)
# Отображаем форму в окне
form.setupUi(window)
# Вызываем метод BatTestForm.update - генерируем первый вопрос
form.update()
# Связываем нажатие на кнопку и метод BatTestForm.check
form.refresh.clicked.connect(form.check)
# Показываем главное окно
window.show()
# Играем победную музыку
playsound("ok.wav", False)
# Запускаем приложение и ждем закрытия
application.exec_()
Вот и все, приложение можно запускать и звать игрока на битву с числами.
Бэтмен ему поможет=)
Итоговая структура проекта содержит код, формочку, 2 иконки и 2 аудио файла
battest
├── batman.png
├── error.wav
├── main.py
├── main.ui
├── ok.wav
└── refresh.png
Заключение
Итак, с помощью Qt и Python мы немного разнообразили довольно скучный учебный процесс и внесли в него немного веселья. Исходный код проекта тут, можете менять его на свое усмотрение, я думаю, другие супергерои тоже не откажут в помощи вашему ребенку.
Хотя, не ограничивайтесь героями, я думаю такие злодеи как Танос - тоже смогут внушить школьнику любовь к математике!
До новых встреч!
Хотя, не ограничивайтесь героями, я думаю такие злодеи как Танос - тоже смогут внушить школьнику любовь к математике!
До новых встреч!
Комментариев нет:
Отправить комментарий