Skip to content

Commit be9de0d

Browse files
authored
Merge pull request larymak#180 from ehcelino/main
GUI demonstration - PyQuiz
2 parents 50462af + 3b09ffb commit be9de0d

File tree

9 files changed

+923
-59
lines changed

9 files changed

+923
-59
lines changed

GUI/Dates/README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
Dates is a simple script to demonstrate both the use of PySimpleGUI as an interface to python scripts,
2+
and basic date manipulation.
3+
4+
It requires PySimpleGUI==4.60.1
5+
6+
Tested on Python 3.10
7+
8+
9+
Eduardo C. (https://github.com/ehcelino)

GUI/Dates/main.py

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
"""
2+
Dates - a simple graphic dates calculator
3+
Demonstrates the use of PySimpleGui as an interface
4+
and date arithmetics using module datetime and numpy.
5+
2022 Eduardo C. - https://github.com/ehcelino
6+
"""
7+
from datetime import datetime
8+
import PySimpleGUI as sg
9+
import numpy as np
10+
11+
DATE_FRMT = '%m-%d-%Y'
12+
13+
def days_between(date_one, date_two):
14+
"""
15+
Determines how many days between dates.
16+
:param date_one: date (us format) as string
17+
:param date_two: date (us format) as string
18+
:return: days as string
19+
"""
20+
result = ''
21+
try:
22+
tmp_one = datetime.strptime(date_one, DATE_FRMT)
23+
tmp_two = datetime.strptime(date_two, DATE_FRMT)
24+
except ValueError as exc:
25+
sg.popup('Error:', exc)
26+
else:
27+
mytimedelta = tmp_one - tmp_two
28+
result = mytimedelta.days
29+
return result
30+
31+
def workdays_between(date_one, date_two):
32+
"""
33+
Determines how many workdays between dates.
34+
:param date_one: date (us format) as string
35+
:param date_two: date (us format) as string
36+
:return: days as int
37+
"""
38+
result = ''
39+
try:
40+
tmp_one = datetime.strptime(date_one, DATE_FRMT)
41+
tmp_two = datetime.strptime(date_two, DATE_FRMT)
42+
except ValueError as exc:
43+
sg.popup('Error:', exc)
44+
else:
45+
result = np.busday_count(tmp_one.strftime('%Y-%m-%d'), tmp_two.strftime('%Y-%m-%d'))
46+
return result
47+
48+
def main_window():
49+
"""
50+
Defines the main window.
51+
:return: PySimpleGUI Window object.
52+
"""
53+
tsz = (8, 1) # Makes easier to define sizes to multiple elements.
54+
isz = (15, 1)
55+
# Everything bound by []'s goes on one line.
56+
layout = [
57+
[sg.Text('Date calculator', font='_ 12 bold')],
58+
[sg.Text('Date format: US (mm-dd-yyyy', font='_ 10 italic')],
59+
[sg.Text('Date one:', size=tsz),
60+
sg.Input('', size=isz, key='-DATE01-')],
61+
[sg.Text('Date two:', size=tsz),
62+
sg.Input('', size=isz, key='-DATE02-')],
63+
[sg.Text('Answer:', size=tsz),
64+
sg.Input('', size=isz, key='-OUTPUT-')],
65+
[sg.Push(), sg.Button('Days between dates', key='-BETWEEN-'), sg.Push()],
66+
[sg.Push(), sg.Button('Working days bt. dates', key='-WORKING-'), sg.Push()],
67+
[sg.Push(), sg.Button('Exit', key='-EXIT-')]
68+
]
69+
70+
return sg.Window('Date calculator!', layout, finalize=True)
71+
72+
window = main_window()
73+
74+
while True: # This is the main loop.
75+
event, values = window.read()
76+
77+
if event == '-BETWEEN-':
78+
try:
79+
window['-OUTPUT-'].update(value=str(abs(
80+
days_between(values['-DATE01-'], values['-DATE02-']))))
81+
except TypeError as err:
82+
sg.popup('Error:', err)
83+
84+
if event == '-WORKING-':
85+
try:
86+
window['-OUTPUT-'].update(value=str(abs(
87+
workdays_between(values['-DATE01-'], values['-DATE02-']))))
88+
except TypeError as err:
89+
sg.popup('Error:', err)
90+
91+
if event in (sg.WIN_CLOSED, '-EXIT-'):
92+
break
93+
94+
window.close()

GUI/PyQuiz/README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
PyQuiz is a simple script to demonstrate both the use of PySimpleGUI as an interface to python scripts,
2+
and dictionaries for storing data. The code is mostly commented and as easy to understand as I could make it.
3+
4+
It requires PySimpleGUI==4.60.1
5+
6+
Tested on Python 3.10
7+
8+
9+
Eduardo C. (https://github.com/ehcelino)

GUI/PyQuiz/main.py

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
"""
2+
PyQuiz - a simple graphical quiz software
3+
Demonstrates the use of PySimpleGui as an interface
4+
and simple dictionary interaction
5+
2022 Eduardo C. - https://github.com/ehcelino
6+
"""
7+
import PySimpleGUI as sg
8+
9+
# The dictionary containing our questions and answers (can come from a file, a database...)
10+
datatable = {
11+
"1": {
12+
"question": "10 + 10",
13+
"answers": {
14+
"a": "20",
15+
"b": "100",
16+
"c": "1010",
17+
},
18+
"correct_answer": "a",
19+
},
20+
"2": {
21+
"question": "5 * 5",
22+
"answers": {
23+
"a": "55",
24+
"b": "25",
25+
"c": "500",
26+
},
27+
"correct_answer": "b",
28+
},
29+
"3": {
30+
"question": "3 ** 2",
31+
"answers": {
32+
"a": "3",
33+
"b": "32",
34+
"c": "9",
35+
},
36+
"correct_answer": "c",
37+
},
38+
}
39+
40+
# Our window definition.
41+
def main_window():
42+
"""
43+
Defines the main window.
44+
:return: PySimpleGUI Window object.
45+
"""
46+
# Everything bound by []'s goes on one line.
47+
layout = [
48+
[sg.Text('Quiz!', font='_ 12 bold')],
49+
[sg.Text('Question:')],
50+
[sg.Input('', size=(30, 1), key='-QUESTION-')],
51+
[sg.Text('Answers:')],
52+
[sg.Multiline('', size=(30, 8), key='-OPTIONS-')],
53+
[sg.Radio('a', group_id='-RADIO-', key='a'),
54+
sg.Radio('b', group_id='-RADIO-', key='b'),
55+
sg.Radio('c', group_id='-RADIO-', key='c'),],
56+
[sg.Button('Start', key='-START-'), sg.Button('Answer', key='-ANSWER-'),
57+
sg.Button('Exit', key='-EXIT-')]
58+
]
59+
60+
return sg.Window('Quiz!', layout, finalize=True)
61+
62+
window = main_window()
63+
64+
# variables
65+
QUESTIONS_INDEX = 1
66+
END = False # To keep track of the end of the game
67+
ANSWERED = False # If the question is still unanswered
68+
QUESTIONING = False # If there's an active question
69+
CORRECT = 0
70+
71+
# aliases
72+
question = window['-QUESTION-']
73+
answers = window['-OPTIONS-']
74+
75+
while True: # This is the main loop.
76+
event, values = window.read()
77+
78+
if event == '-START-':
79+
if not END:
80+
QUESTIONING = True
81+
answers.update(value='')
82+
question.update(value=f'{datatable[str(QUESTIONS_INDEX)]["question"]}')
83+
for answer, answer_data in datatable[str(QUESTIONS_INDEX)]["answers"].items():
84+
answers.print(f'({answer}): {answer_data}')
85+
correct_answer = datatable[str(QUESTIONS_INDEX)]["correct_answer"]
86+
ANSWERED = False
87+
else:
88+
QUESTIONING = False
89+
sg.popup('End of Quiz.')
90+
91+
if event == '-ANSWER-':
92+
if (values['a'] or values['b'] or values['c']) and QUESTIONING:
93+
for idx in ('a', 'b', 'c'):
94+
if values[idx]:
95+
USER_CHOICE = idx
96+
if not ANSWERED:
97+
if USER_CHOICE == correct_answer:
98+
sg.popup('Correct!')
99+
CORRECT += 1
100+
else:
101+
sg.popup('Wrong.')
102+
if not ANSWERED:
103+
QUESTIONS_INDEX += 1
104+
ANSWERED = True
105+
if QUESTIONS_INDEX > len(datatable):
106+
END = True
107+
sg.popup(f'The end. You got {CORRECT} of {len(datatable)}.')
108+
if not END:
109+
window.write_event_value('-START-', '')
110+
111+
if event in (sg.WIN_CLOSED, '-EXIT-'):
112+
break
113+
114+
115+
window.close()

GUI/QtQuiz/README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
QtQuiz is a simple script to demonstrate both the use of PyQT5 as an interface to python scripts,
2+
and dictionaries for storing data. The code is mostly commented and as easy to understand as I could make it.
3+
4+
It requires PyQt5==5.15.7
5+
6+
Tested on Python 3.10
7+
8+
9+
Eduardo C. (https://github.com/ehcelino)

GUI/QtQuiz/design.py

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
# -*- coding: utf-8 -*-
2+
3+
# Form implementation generated from reading ui file '.\design.ui'
4+
#
5+
# Created by: PyQt5 UI code generator 5.15.7
6+
#
7+
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
8+
# run again. Do not edit this file unless you know what you are doing.
9+
10+
11+
from PyQt5 import QtCore, QtGui, QtWidgets
12+
13+
14+
class Ui_MainWindow(object):
15+
def setupUi(self, MainWindow):
16+
MainWindow.setObjectName("MainWindow")
17+
MainWindow.resize(420, 417)
18+
self.centralwidget = QtWidgets.QWidget(MainWindow)
19+
font = QtGui.QFont()
20+
font.setFamily("Calibri")
21+
font.setPointSize(12)
22+
self.centralwidget.setFont(font)
23+
self.centralwidget.setObjectName("centralwidget")
24+
self.label = QtWidgets.QLabel(self.centralwidget)
25+
self.label.setGeometry(QtCore.QRect(10, 20, 221, 16))
26+
self.label.setObjectName("label")
27+
self.txtQuestion = QtWidgets.QTextEdit(self.centralwidget)
28+
self.txtQuestion.setGeometry(QtCore.QRect(10, 70, 401, 61))
29+
self.txtQuestion.setReadOnly(True)
30+
self.txtQuestion.setObjectName("txtQuestion")
31+
self.label_2 = QtWidgets.QLabel(self.centralwidget)
32+
self.label_2.setGeometry(QtCore.QRect(10, 50, 71, 16))
33+
self.label_2.setObjectName("label_2")
34+
self.label_3 = QtWidgets.QLabel(self.centralwidget)
35+
self.label_3.setGeometry(QtCore.QRect(10, 140, 21, 16))
36+
self.label_3.setObjectName("label_3")
37+
self.label_4 = QtWidgets.QLabel(self.centralwidget)
38+
self.label_4.setGeometry(QtCore.QRect(10, 170, 21, 16))
39+
self.label_4.setObjectName("label_4")
40+
self.label_5 = QtWidgets.QLabel(self.centralwidget)
41+
self.label_5.setGeometry(QtCore.QRect(10, 200, 21, 16))
42+
self.label_5.setObjectName("label_5")
43+
self.label_6 = QtWidgets.QLabel(self.centralwidget)
44+
self.label_6.setGeometry(QtCore.QRect(10, 230, 21, 16))
45+
self.label_6.setObjectName("label_6")
46+
self.txtAnswerA = QtWidgets.QLineEdit(self.centralwidget)
47+
self.txtAnswerA.setGeometry(QtCore.QRect(30, 140, 381, 20))
48+
self.txtAnswerA.setReadOnly(True)
49+
self.txtAnswerA.setObjectName("txtAnswerA")
50+
self.txtAnswerB = QtWidgets.QLineEdit(self.centralwidget)
51+
self.txtAnswerB.setGeometry(QtCore.QRect(30, 170, 381, 20))
52+
self.txtAnswerB.setReadOnly(True)
53+
self.txtAnswerB.setObjectName("txtAnswerB")
54+
self.txtAnswerC = QtWidgets.QLineEdit(self.centralwidget)
55+
self.txtAnswerC.setGeometry(QtCore.QRect(30, 200, 381, 20))
56+
self.txtAnswerC.setReadOnly(True)
57+
self.txtAnswerC.setObjectName("txtAnswerC")
58+
self.txtAnswerD = QtWidgets.QLineEdit(self.centralwidget)
59+
self.txtAnswerD.setGeometry(QtCore.QRect(30, 230, 381, 20))
60+
self.txtAnswerD.setReadOnly(True)
61+
self.txtAnswerD.setObjectName("txtAnswerD")
62+
self.label_7 = QtWidgets.QLabel(self.centralwidget)
63+
self.label_7.setGeometry(QtCore.QRect(10, 260, 91, 16))
64+
self.label_7.setObjectName("label_7")
65+
self.txtOne = QtWidgets.QLineEdit(self.centralwidget)
66+
self.txtOne.setGeometry(QtCore.QRect(320, 30, 21, 20))
67+
self.txtOne.setReadOnly(True)
68+
self.txtOne.setObjectName("txtOne")
69+
self.label_8 = QtWidgets.QLabel(self.centralwidget)
70+
self.label_8.setGeometry(QtCore.QRect(350, 30, 21, 16))
71+
self.label_8.setObjectName("label_8")
72+
self.txtN = QtWidgets.QLineEdit(self.centralwidget)
73+
self.txtN.setGeometry(QtCore.QRect(370, 30, 21, 20))
74+
self.txtN.setReadOnly(True)
75+
self.txtN.setObjectName("txtN")
76+
self.btnStart = QtWidgets.QPushButton(self.centralwidget)
77+
self.btnStart.setGeometry(QtCore.QRect(10, 360, 71, 41))
78+
self.btnStart.setObjectName("btnStart")
79+
self.btnAnswer = QtWidgets.QPushButton(self.centralwidget)
80+
self.btnAnswer.setGeometry(QtCore.QRect(90, 360, 71, 41))
81+
self.btnAnswer.setObjectName("btnAnswer")
82+
self.btnExit = QtWidgets.QPushButton(self.centralwidget)
83+
self.btnExit.setGeometry(QtCore.QRect(340, 360, 71, 41))
84+
self.btnExit.setObjectName("btnExit")
85+
self.radA = QtWidgets.QRadioButton(self.centralwidget)
86+
self.radA.setGeometry(QtCore.QRect(110, 260, 31, 17))
87+
self.radA.setObjectName("radA")
88+
self.radB = QtWidgets.QRadioButton(self.centralwidget)
89+
self.radB.setGeometry(QtCore.QRect(150, 260, 31, 17))
90+
self.radB.setObjectName("radB")
91+
self.radC = QtWidgets.QRadioButton(self.centralwidget)
92+
self.radC.setGeometry(QtCore.QRect(190, 260, 31, 17))
93+
self.radC.setObjectName("radC")
94+
self.radD = QtWidgets.QRadioButton(self.centralwidget)
95+
self.radD.setGeometry(QtCore.QRect(230, 260, 31, 17))
96+
self.radD.setObjectName("radD")
97+
self.txtResult = QtWidgets.QLineEdit(self.centralwidget)
98+
self.txtResult.setGeometry(QtCore.QRect(80, 300, 251, 20))
99+
self.txtResult.setFocusPolicy(QtCore.Qt.StrongFocus)
100+
self.txtResult.setAlignment(QtCore.Qt.AlignCenter)
101+
self.txtResult.setReadOnly(True)
102+
self.txtResult.setObjectName("txtResult")
103+
MainWindow.setCentralWidget(self.centralwidget)
104+
105+
self.retranslateUi(MainWindow)
106+
QtCore.QMetaObject.connectSlotsByName(MainWindow)
107+
108+
def retranslateUi(self, MainWindow):
109+
_translate = QtCore.QCoreApplication.translate
110+
MainWindow.setWindowTitle(_translate("MainWindow", "QtQuiz!"))
111+
self.label.setText(_translate("MainWindow", "QtQuiz! - Questions and answers"))
112+
self.label_2.setText(_translate("MainWindow", "Question:"))
113+
self.label_3.setText(_translate("MainWindow", "a)"))
114+
self.label_4.setText(_translate("MainWindow", "b)"))
115+
self.label_5.setText(_translate("MainWindow", "c)"))
116+
self.label_6.setText(_translate("MainWindow", "d)"))
117+
self.label_7.setText(_translate("MainWindow", "Your answer:"))
118+
self.label_8.setText(_translate("MainWindow", "of"))
119+
self.btnStart.setText(_translate("MainWindow", "Start"))
120+
self.btnAnswer.setText(_translate("MainWindow", "Answer"))
121+
self.btnExit.setText(_translate("MainWindow", "Exit"))
122+
self.radA.setText(_translate("MainWindow", "a"))
123+
self.radA.setShortcut(_translate("MainWindow", "A"))
124+
self.radB.setText(_translate("MainWindow", "b"))
125+
self.radB.setShortcut(_translate("MainWindow", "B"))
126+
self.radC.setText(_translate("MainWindow", "c"))
127+
self.radC.setShortcut(_translate("MainWindow", "C"))
128+
self.radD.setText(_translate("MainWindow", "d"))
129+
self.radD.setShortcut(_translate("MainWindow", "D"))

0 commit comments

Comments
 (0)