Create a Quiz App with Tkinter & Pandas Subtitle: Step-by-step tutorial — Python GUI reading questions from Excel Small note: Requires Python 3.8+ and pandas installed.

What you will learn

  1. How to prepare an Excel file with questions.

  2. How to load questions using pandas.

  3. How to build the Tkinter UI (buttons, labels, images).

  4. How to implement quiz logic: scoring, navigation and restart.

  5. How to customize the look and pack your app.

Prerequisites

  • Python 3.8+ installed.

  • Basic Python knowledge (functions, lists, variables).

  • Install pandas with:

pip install pandas openpyxl

(openpyxl is used by pandas to read .xlsx files.)

Project files

Create a project folder with these files:

  • quiz_app.py — the Python script (code below)

  • questions.xlsx — Excel file with questions and options

  • logo.png — small logo image for the app (optional)

Prepare questions.xlsx

Create an Excel file with these columns in the first row (header):

question | option1 | option2 | option3 | option4 | answer

  • question — the question text.

  • option1..option4 — the four choices.

  • answer — integer 1..4 pointing to the correct option.

Add at least 10 rows (each row is a question). Save as questions.xlsx in the same folder as the script.

Full code (copy into quiz_app.py)

import tkinter as tk 
from tkinter import messagebox
from tkinter import PhotoImage

import pandas as pd 
import random

# Load the excel file
df = pd.read_excel('questions.xlsx')

# Randomly select questions
questions = df.sample(n=10).values.tolist()

# Global variables
score = 0
current_question = 0

# Function to display the next Question
def display_question():
	question, option1, option2, option3, option4, answer = questions[current_question]
	question_label.config(text=question)
	option1_btn.config(text=option1, state=tk.NORMAL, command=lambda: check_answer(1))
	option2_btn.config(text=option2, state=tk.NORMAL, command=lambda: check_answer(2))
	option3_btn.config(text=option3, state=tk.NORMAL, command=lambda: check_answer(3))
	option4_btn.config(text=option4, state=tk.NORMAL, command=lambda: check_answer(4))
	correct_answer.set(answer)


# Funcytion to check the answer
def check_answer(answer):
	global score, current_question

	if answer == correct_answer.get():
		score +=1

	current_question +=1

	if current_question < len(questions):
		display_question()
	else:
		show_result()

# function to show the results
def show_result():
	messagebox.showinfo("Quiz Completed", f"Congratulations you finished the quiz. \n\nFinal Score: {score}/{len(questions)}")
	option1_btn.config(state=tk.DISABLED)
	option2_btn.config(state=tk.DISABLED)
	option3_btn.config(state=tk.DISABLED)
	option4_btn.config(state=tk.DISABLED)
	play_again_btn.pack()

# function to play agin
def play_again():
	global score, current_question
	score = 0 
	current_question = 0
	random.shuffle(questions)
	display_question()
	option1_btn.config(state=tk.NORMAL)
	option2_btn.config(state=tk.NORMAL)
	option3_btn.config(state=tk.NORMAL)
	option4_btn.config(state=tk.NORMAL)

	play_again_btn.pack_forget()



# Define
background_color = "#ECECEC"
text_color = "#333333"
button_color = "#4CAF50"
button_text_color = "#FFFFFF"

#window
window = tk.Tk()
window.title("Quiz App")
window.geometry("400x450")
window.config(bg=background_color)
window.option_add('*Font', "Arial")

# App logo
app_icon = PhotoImage(file='logo.png')
app_label = tk.Label(window, image=app_icon, bg=background_color)
app_label.pack(pady=10)


# interface components
question_label = tk.Label(window, text="Hello Joao",wraplength=380, bg=background_color,fg=text_color, font=("Arial", 12, "bold") )
question_label.pack(pady=20)


correct_answer = tk.IntVar()
option1_btn = tk.Button(window, text="", width=30, bg=button_color,fg=button_text_color, state=tk.DISABLED, font=("Arial", 10, "bold") )
option1_btn.pack(pady=10)

option2_btn = tk.Button(window, text="", width=30, bg=button_color,fg=button_text_color, state=tk.DISABLED, font=("Arial", 10, "bold") )
option2_btn.pack(pady=10)

option3_btn = tk.Button(window, text="", width=30, bg=button_color,fg=button_text_color, state=tk.DISABLED, font=("Arial", 10, "bold") )
option3_btn.pack(pady=10)

option4_btn = tk.Button(window, text="", width=30, bg=button_color,fg=button_text_color, state=tk.DISABLED, font=("Arial", 10, "bold") )
option4_btn.pack(pady=10)

play_again_btn = tk.Button(window, text="Play Again", width=30, bg=button_color,fg=button_text_color, font=("Arial", 10, "bold"), command=play_again )



display_question()


window.mainloop()

Explain the main parts

  • Load questions: df = pd.read_excel('questions.xlsx') reads your Excel into a DataFrame.

  • Random sample: df.sample(n=10) picks 10 questions at random.

  • State variables: score and current_question track progress.

  • display_question(): writes the current question and attaches button callbacks.

  • check_answer(): compares the chosen answer with the correct one and updates the score.

  • show_result(): displays the final score with a popup and disables buttons.

Tips & improvements

  • Validate the Excel file (empty rows, missing columns) before using.

  • Use try/except around pd.read_excel to show a friendly error if file missing.

  • Add a progress bar or question counter: "Question 3 / 10".

  • Add categories: include a category column and filter by it before sampling.

  • Save high scores to a local file (CSV) to show the best scores.

Styling suggestions for Canva

  • Use a clean header font (e.g., Montserrat) for titles.

  • Use code blocks with a monospaced font (Courier New) and a subtle gray background.

  • Add screenshots of the running app: take a screenshot on your OS and paste into Canva.

  • Use icons for each step (install, file, code, run) to make slides visual.

Final notes & sharing

  • To run: open a terminal in the project folder and run python quiz_app.py.

  • If you plan to share on GitHub, include requirements.txt with pandas and openpyxl.