I wrote a script that gives the user a quick arithmetic quiz and results using a tkinter window.
I am very new to programming, and this is also my first time using tkinter as well.
import random, tkinter as tk
from tkinter import Button, Frame, Label, Entry, Tk as initializeRoot
class TkWindows:
def __init__(self) -> None:
pass
def createFrame(self, root) :
frame = Frame(root)
frame.pack(expand=True)
return frame
def modeSelection(self, windowDims: list = [300, 300], mode: str | None = None, modeOptions: list=['Addition', 'Subtraction', 'Multiplication', 'Division']) -> str :
# Gets the chosen mode and closes the window
def getModeChoice(selectedOption: str, root) -> None:
nonlocal mode
mode = selectedOption
root.destroy()
# Initializes the window
root = initializeRoot()
root.title('Select Mode')
# Initializes window dimensions
screenDims = [root.winfo_screenwidth(), root.winfo_screenheight()]
windowCoords = [int((screenDims[0] - windowDims[0]) / 2), int((screenDims[1] - windowDims[1]) / 2)]
root.geometry(f"{windowDims[0]}x{windowDims[1]}+{windowCoords[0]}+{windowCoords[1]}")
# Adds window frame and elements
frame = self.createFrame(root)
for option in modeOptions:
button = Button(frame, text=option, command=lambda opt=option: getModeChoice(opt, root))
button.pack(pady=5, fill=tk.X)
root.mainloop()
return mode
def questions(self, questionList: list, operationSymbol: str, mode: str, responseList: list = [], windowDims: list=[300,200], questionIndex: int = 0) -> list :
def getResponse(root, entry) -> None:
answers = entry.get()
responseList.append(answers)
nonlocal questionIndex
questionIndex += 1
if questionIndex < len(questionList) :
entry.delete(0, tk.END)
questionLabel.config(text=str(questionList[questionIndex][0]) + ' ' + operationSymbol + ' ' + str(questionList[questionIndex][1]))
questionCounter.config(text=('Question ' + str(questionIndex + 1) + ' out of ' + str(len(questionList))))
else :
root.destroy()
root = initializeRoot()
root.title(str(mode))
screenDims = [root.winfo_screenwidth(), root.winfo_screenheight()]
windowCoords = [int((screenDims[0] - windowDims[0]) / 2), int((screenDims[1] - windowDims[1]) / 2)]
root.geometry(f"{windowDims[0]}x{windowDims[1]}+{windowCoords[0]}+{windowCoords[1]}")
frame = self.createFrame(root)
questionCounter = Label(frame, text=('Question ' + str(questionIndex + 1) + ' out of ' + str(len(questionList))), font=("Arial", 16))
questionCounter.pack(pady=5)
questionLabel = Label(frame, text=(str(questionList[0][0]) + ' ' + operationSymbol + ' ' + str(questionList[0][1])), font=("Arial", 20))
questionLabel.pack(pady=5)
textBox = Entry(frame)
textBox.pack(pady=5)
enterButton = tk.Button(frame, text='Enter', command=lambda: getResponse(root, textBox))
enterButton.pack(pady=5)
tk.mainloop()
return responseList
def questionResults(self, questionList: list, responseList: list, operationSymbol: str, windowDims: list=[300, 250], questionsPerPage: int=5, pageIndex: int=0, correctQuestions: list=[], incorrectQuestions: list=[], incorrectQuestionsWithResponse: list=[], incorrectLabels: list=[]) -> None:
for i in range(len(responseList)) :
questionString = str(questionList[i][0]) + ' ' + operationSymbol + ' ' + str(questionList[i][1]) + ' = ' + str(questionList[i][2])
if str(responseList[i]) == str(questionList[i][2]) :
correctQuestions.append(questionString)
else:
incorrectQuestions.append(questionString)
incorrectQuestionsWithResponse.append(questionString + ' | Your answer was: ' + str(responseList[i]))
if len(incorrectQuestions) > 0 :
def nextPage(root) :
nonlocal pageIndex
pageIndex += 1
if pageIndex * questionsPerPage >= len(incorrectQuestions) :
root.destroy()
else :
for i in range(questionsPerPage) :
try :
newLabel = incorrectQuestionsWithResponse[i + pageIndex * questionsPerPage]
except IndexError :
newLabel = ' '
incorrectLabels[i].config(text=newLabel)
root = initializeRoot()
root.title('Score: ' + str(len(correctQuestions)) + '/' + str(len(questionList)))
screenDims = [root.winfo_screenwidth(), root.winfo_screenheight()]
windowCoords = [int((screenDims[0] - windowDims[0]) / 2), int((screenDims[1] - windowDims[1]) / 2)]
root.geometry(f"{windowDims[0]}x{windowDims[1]}+{windowCoords[0]}+{windowCoords[1]}")
frame = self.createFrame(root)
resultsTitle = Label(frame, text='You missed the following questions:')
resultsTitle.pack(pady=5)
for i in range(questionsPerPage) :
try :
incorrectLabels.append(Label(frame, text=(incorrectQuestionsWithResponse[i])))
except IndexError :
incorrectLabels.append(Label(frame, text=' '))
incorrectLabels[i].pack(pady=5)
continueButton = Button(frame, text='Continue:', command=lambda: nextPage(root))
continueButton.pack(pady=5)
root.mainloop()
createWindow = TkWindows()
class Main :
def __init__(self) -> None:
self.sessionMode: str | None = None
self.questionList: list = []
self.operationSymbol: str | None = None
self.responseList: list = []
def createQuestions(self, sessionMode, numOfQuestions: int=15, questionList: list=[], operationSymbol: str | None=None, operationModeDict: dict[str:str]={'Addition' : '+', 'Subtraction' : '-', 'Multiplication' : 'x', 'Division' : '÷'}) -> tuple[list, str]:
operationSymbol = operationModeDict[sessionMode]
while len(questionList) < numOfQuestions :
questionElements = (random.randint(1,10), random.randint(1,10))
if sessionMode == 'Addition':
question = (questionElements[0], questionElements[1], questionElements[0] + questionElements[1])
elif sessionMode == 'Subtraction':
question = (questionElements[0] + questionElements[1], questionElements[0], questionElements[1])
elif sessionMode == 'Multiplication':
question = (questionElements[0], questionElements[1], questionElements[0] * questionElements[1])
elif sessionMode == 'Division':
question = (questionElements[0] * questionElements[1], questionElements[0], questionElements[1])
if question not in questionList :
questionList.append(question)
return questionList, operationSymbol
def runMain(self) :
self.sessionMode = createWindow.modeSelection()
if self.sessionMode != None :
self.questionList, self.operationSymbol = self.createQuestions(self.sessionMode)
self.responseList = createWindow.questions(self.questionList, self.operationSymbol, self.sessionMode)
createWindow.questionResults(self.questionList, self.responseList, self.operationSymbol)
main = Main()
main.runMain()