A Free Test Maker with Python and Tkinter

Due to a request, I made this simple code to make a test with tkinter. It is very rough, but the logic works, so that  you can make the adjustment you want to make it seem prettier.

The starting window

In the main window there is a little explanation of what to do.

import tkinter as tk

root = tk.Tk()
label = tk.Label(root, text="TEST", bg="gold", fg="blue", font="Arial 24")
label.pack()
text = tk.Text(root)
text.pack()
root.mainloop()

This is the window with the label and a text widget. Let’s add the code to create the questions.

The window for the test

Your question go here:

quest = [
		("what is 1+1?","2"),
		("What is 50*2?","100"),
		("What is the capital of Italy?", "Rome")
]

This is where you put your questions and answers. It’s all you need to change to personalize the test. It will work with as many questions you want.

The question will have this way to show themselves. There is the focus on the entry, so that you can answer without having to position yourself on the widget with the mouse. You just write and then hit Enter… and you go to the next question. As fast as you want.

The final window

When the test ends, you see the score and you can close the window pressing the button.

The entire code

This is the code of the program to make tests with python and tkinter.

import tkinter as tk

quest = [
		("what is 1+1?","2"),
		("What is 50*2?","100"),
		("What is the capital of Italy?", "Rome")
]
numdom = len(quest)
score = 0
num = 0
def d1():
	global num, score, entry
	if num == numdom:
		text.pack_forget()
		entry.pack_forget()
		button['text'] = f"Score {score}\n Click to Close this window"
		button['command'] = game_over
		button.pack()
		return

	if num == 0:
		answer_widget()
	root.geometry("400x200+100+200")
	text['height'] = 1
	text['bg'] = 'cyan'
	text['width'] = 50
	text.delete("1.0",tk.END)
	text.insert("1.0",quest[num][0])
	button.pack_forget()
	num+=1

def game_over():
	root.destroy()

def answer_widget():
	global entry
	entry = tk.Entry(root, textvariable=solution, bg="yellow", font="Arial 20")
	entry.pack()
	entry.bind("<Return>", lambda x: check())
	entry.focus()

def check():
	global n, score
	if solution.get() == quest[num-1][1]:
		text.insert(tk.END, "Right")
		score+=1
	else:
		text.insert(tk.END, "Wrong")
	solution.set("")
	d1()

root = tk.Tk()
label = tk.Label(root, text = """Test""", bg="coral", font="Arial 48")
label.pack()
rules = """Answer to the Following questions

Click on the button below to start
You will see a question
Write your answer and press Enter
"""
text = tk.Text(root, height=12,font="Arial 20")
text.insert("1.0", rules)
text.pack()
button = tk.Button(root, text="Click To Start", bg="black", fg="white", command=d1, font="Arial 20")
button.pack()
solution = tk.StringVar()

root.mainloop()

A video that shows the output of the test program

Some changes in the score

I added some more features:

  • You can see if the answer is right or wrong after each answer
  • There is a little pause among questions to let you see the result
  • you can see the total score
  • you get a percentage of the result at the end
  • color changes if you are wright or wrong
import tkinter as tk


quest = [
		#1
		("""I Paesi che negli ultimi anni hanno
registrato elevati aumenti di spese per il
turismo outgoing sono la Cina e la Russia.""","v"),
		#2
		("""
Secondo l’OMT un visitatore è considerato
un turista se effettua almeno tre
pernottamenti nella località visitata.
			""","f"),
		#3
		("""Nel 2014 il continente più visitato dai
turisti di tutto il mondo è stato l’Asia.""", "f"),
#4
("""Negli ultimi anni i flussi turistici
internazionali sono cresciuti a un tasso
medio del 4,5% l’anno.
""","v")

]
numdom = len(quest)
score = 0
num = 0
def d1():
	global num, score, entry
	if num == numdom:
		text.pack_forget()
		entry.pack_forget()
		score = score / num * 100
		button['text'] = f"Score {score}%\n Click to Close this window"
		button['command'] = game_over
		button.pack()
		return

	if num == 0:
		answer_widget()
	text['height'] = 7
	text['bg'] = 'cyan'
	text['width'] = 80
	text.delete("1.0",tk.END)
	text.insert("1.0",quest[num][0] + "[v][f]")
	button.pack_forget()
	num+=1

def game_over():
	global score
	print(score)
	root.destroy()

def answer_widget():
	global entry
	entry = tk.Entry(root, textvariable=solution, bg="yellow", font="Arial 20")
	entry.pack()
	entry.bind("<Return>", lambda x: check())
	entry.focus()

def empty_textbox():
		solution.set("")
		d1()

def check():
	global n, score
	text.delete("1.0",tk.END)
	if solution.get() == quest[num-1][1]:
		text.insert(tk.END, "Right +1")
		score+=1
		text['bg'] = "green"
	else:
		text.insert(tk.END, "Wrong 0 points")
		text['bg'] = "red"
	label['text'] = score
	text.after(1000, empty_textbox)

root = tk.Tk()
label = tk.Label(root, text = """Test""", bg="coral", font="Arial 48")
label.pack()
rules = """Answer to the Following questions

Click on the button below to start
You will see a question
Write your answer and press Enter
"""
text = tk.Text(root, height=12,font="Arial 20")
text.insert("1.0", rules)
text.pack()
button = tk.Button(root, text="Click To Start", bg="black", fg="white", command=d1, font="Arial 20")
button.pack()
solution = tk.StringVar()

root.mainloop()

A test with 2 possible answer in no time at all

Let’s see how we can adapt the code so that we do not have to write all the questions with the answer alongside when you have just to possible answer, like in true false test or any other test with the same two (or three, four…) possible answer. How you do it?

1. Create a list for each answer

f = """Denaro in Cassa
Banca x c/c
Crediti v/clienti
Debiti v/fornitori
Iva a ns credito
Iva a ns debito
Mutui passivi
Ratei passivi
Ratei crediti
""".splitlines()

The list above contains the list that has “f” (financial accounts)

e = """Merci c/acquisti
Merci c/vendite
Attrezzature
Stipendi
Arredi
Brevetti
Software
Computer
Tovagliato
Utenze elettriche
Utenze telefoniche
""".splitlines()

This are the economic accounts list.

Then we join and shuffle these lists into one:

num_questions = len(f) + len(e)

fe = f + e
shuffle(fe)
answer = []
for q in fe:
	if q in f:
		answer.append("f")
	else:
		answer.append("e")

Above we created a list with the solution of the fe shuffled accounts

Now we have to take this data into the quest list of tuples that we used in the program to make our question. The quest data are tuples with a question and the answer as items of the tuple. We get the first by the fe list and the seccond by the answer list.

quest = []
for n in range(num_questions):
	quest.append((fe[n], answer[n]))

Now that we built our data into quest, the code can do his job like it always did when we were adding manually each question. That is why I entitles …. in no time. This can be adapted to True False or other tests with other alternative (also more than 2 lists).

The whole code

import tkinter as tk
from random import shuffle

f = """Denaro in Cassa
Banca x c/c
Crediti v/clienti
Debiti v/fornitori
Iva a ns credito
Iva a ns debito
Mutui passivi
Ratei passivi
Ratei crediti
""".splitlines()

e = """Merci c/acquisti
Merci c/vendite
Attrezzature
Stipendi
Arredi
Brevetti
Software
Computer
Tovagliato
Utenze elettriche
Utenze telefoniche
""".splitlines()

num_questions = len(f) + len(e)

fe = f + e
shuffle(fe)


answer = []
for q in fe:
	if q in f:
		answer.append("f")
	else:
		answer.append("e")

quest = []
for n in range(num_questions):
	quest.append((fe[n], answer[n]))

print(quest)


numdom = len(quest)
score = 0
num = 0
def d1():
	global num, score, entry
	if num == numdom:
		text.pack_forget()
		entry.pack_forget()
		score = score / num * 100
		button['text'] = f"Score {score}%\n Click to Close this window"
		button['command'] = game_over
		button.pack()
		return

	if num == 0:
		answer_widget()
	text['height'] = 7
	text['bg'] = 'cyan'
	text['width'] = 80
	text.delete("1.0",tk.END)
	text.insert("1.0",quest[num][0] + "\n\n Choose among [f][e]")
	button.pack_forget()
	num+=1

def game_over():
	global score
	print(score)
	root.destroy()

def answer_widget():
	global entry
	entry = tk.Entry(root, textvariable=solution, bg="yellow", font="Arial 20")
	entry.pack()
	entry.bind("<Return>", lambda x: check())
	entry.focus()

def empty_textbox():
		solution.set("")
		d1()

def check():
	global n, score
	text.delete("1.0",tk.END)
	if solution.get() == quest[num-1][1]:
		text.insert(tk.END, "Right +1")
		score+=1
		text['bg'] = "green"
	else:
		text.insert(tk.END, "Wrong 0 points")
		text['bg'] = "red"
	label['text'] = score
	text.after(1000, empty_textbox)

root = tk.Tk()
label = tk.Label(root, text = """Test""", bg="coral", font="Arial 48")
label.pack()
rules = """Answer to the Following questions

Click on the button below to start
You will see a question
Write your answer and press Enter
"""
text = tk.Text(root, height=12,font="Arial 20")
text.insert("1.0", rules)
text.pack()
button = tk.Button(root, text="Click To Start", bg="black", fg="white", command=d1, font="Arial 20")
button.pack()
solution = tk.StringVar()

root.mainloop()

 

Tkinter test for students

Tkinter articles

Published by pythonprogramming

Started with basic on the spectrum, loved javascript in the 90ies and python in the 2000, now I am back with python, still making some javascript stuff when needed.