We will develop a modular quiz application using Python's Tkinter for the GUI and JSON for storing and managing quiz data. The application features multiple-choice questions, real-time score tracking, and a visually appealing layout for better user interaction.
The application uses an external JSON file as the data source for questions and answers. Below is a sample JSON structure with two questions.
{
"quiz": [
{
"question": "What does Tkinter stand for?",
"options": [
"Tk Interface",
"Toolkit Interface",
"Test Interface",
"Terminal Kit"
],
"answer": "Tk Interface"
},
{
"question": "Which method is used to start Tkinter's event loop?",
"options": [
"mainloop()",
"startloop()",
"runloop()",
"begin()"
],
"answer": "mainloop()"
}
]
}
Download this json sample file and update the path in your application python file to connect and read the data. The script starts with importing required modules and loading the quiz data from a JSON file.
import tkinter as tk
from tkinter import messagebox
import json
# Load JSON data
with open("quiz_data.json", "r") as file:
quiz_data = json.load(file)
questions = quiz_data.get("quiz", [])
The Tkinter root window is configured with a title, size, and background color for a better user experience.
# Initialize Tkinter
root = tk.Tk()
root.geometry("600x400")
root.title("Quiz Application")
root.configure(bg="#f0f8ff") # Light blue background
Questions and their options are displayed dynamically using labels and radio buttons, which are updated as the user progresses through the quiz.
# Variables
current_question_index = 0
selected_answer = tk.StringVar()
question_text = tk.StringVar()
# Question Label
question_label = tk.Label(
root, textvariable=question_text, font=("Arial", 16, "bold"),
fg="#4caf50", bg="#f0f8ff", wraplength=500, anchor="w"
)
question_label.grid(row=0, column=0, columnspan=2, padx=10, pady=20, sticky="w")
# Radio Buttons for Options
option_buttons = []
for i in range(4):
rb = tk.Radiobutton(
root, text="", variable=selected_answer, value="", font=("Arial", 14),
bg="#f0f8ff", anchor="w", width=40, justify="left", fg="#000"
)
rb.grid(row=i + 1, column=0, columnspan=2, padx=20, pady=5, sticky="w")
option_buttons.append(rb)
The Next button allows users to navigate through questions and calculates the score at the end.
# Handle "Next" button
def next_question():
global current_question_index, score
if not selected_answer.get():
messagebox.showwarning("Warning", "Please select an answer before proceeding!")
return
# Check the answer
if selected_answer.get() == questions[current_question_index]["answer"]:
score += 1
current_question_index += 1
if current_question_index < len(questions):
load_question(current_question_index)
else:
messagebox.showinfo("Quiz Completed", f"Your score is {score}/{len(questions)}")
root.quit()
import tkinter as tk
from tkinter import messagebox
import json
# Load JSON data
with open("E:\\testing\\quiz_v1\\tkinter_quiz.json", "r") as file: # update path
quiz_data = json.load(file)
# Extract questions from JSON
questions = quiz_data.get("quiz", [])
# Initialize Tkinter
root = tk.Tk()
root.geometry("600x400")
root.title("Quiz Application")
# Colors for better look and feel
bg_color = "#f0f8ff" # Light blue
question_color = "#4caf50" # Green
button_color = "#2196f3" # Blue
font_main = ("Arial", 14)
font_question = ("Arial", 16, "bold")
root.configure(bg=bg_color)
# Global Variables
current_question_index = 0
selected_answer = tk.StringVar() # Stores the user's selected answer
score = 0
# Function to load a question
def load_question(index):
global selected_answer
# Clear previous selection (set radio buttons to deselected)
selected_answer.set(None)
# Get the current question
question = questions[index]
question_text.set(f"Q{index + 1}: {question['question']}")
# Update options
for i, option in enumerate(question["options"]):
option_buttons[i].config(text=option, value=option)
# Function to handle "Next" button click
def next_question():
global current_question_index, score
if not selected_answer.get():
messagebox.showwarning("Warning", "Please select an answer before proceeding!")
return
# Check the answer
if selected_answer.get() == questions[current_question_index]["answer"]:
score += 1
# Move to the next question or end the quiz
current_question_index += 1
if current_question_index < len(questions):
load_question(current_question_index)
else:
messagebox.showinfo("Quiz Completed", f"Your score is {score}/{len(questions)}")
root.quit() # Close the application after completion
# UI Components
question_text = tk.StringVar()
# Display Question Label
question_label = tk.Label(
root, textvariable=question_text, font=font_question,
fg=question_color, bg=bg_color, wraplength=500, anchor="w"
)
question_label.grid(row=0, column=0, columnspan=2, padx=10, pady=20, sticky="w")
# Display Options as Radio Buttons
option_buttons = []
for i in range(4): # Assuming 4 options per question
rb = tk.Radiobutton(
root, text="", variable=selected_answer, value="", font=font_main,
bg=bg_color, anchor="w", width=40, justify="left", fg="#000"
)
rb.grid(row=i + 1, column=0, columnspan=2, padx=20, pady=5, sticky="w")
option_buttons.append(rb)
# "Next" Button
next_button = tk.Button(
root, text="Next", command=next_question, bg=button_color,
fg="white", font=font_main, width=12
)
next_button.grid(row=6, column=0, columnspan=2, pady=20)
# Load the first question
load_question(current_question_index)
# Run the application
root.mainloop()
This modular quiz application demonstrates how to integrate Tkinter with JSON to create an interactive, scalable solution. You can easily switch to other data sources, such as SQLite or XML, by updating the data-loading logic.