1. 项目概述与需求分析

本教程将带你从零开始,用 Python 标准库自带的 Tkinter 构建一个带图形界面的教育测验软件,并最终打包成单个 EXE 文件。整个项目不依赖任何第三方付费库,代码量精简、逻辑清晰,非常适合编程新手练手,也可以作为教师制作课堂测验工具的参考模板。

1.1 核心功能清单

  • 图形化界面:使用 Tkinter 构建窗口、按钮、单选框、标签等标准组件
  • 题库加载:从 JSON 文件读取题目、选项和正确答案,零基础也能修改题库内容
  • 逐题作答:用户选择答案后点击“下一题”自动判断对错并计分
  • 实时分数反馈:每完成一题即时显示当前得分和正确率
  • 测验结果报告:全部答完后弹出成绩总结窗口,展示得分、正确率和用时
  • 打包为 EXE:使用 PyInstaller 将 Python 脚本打包成独立 EXE,无需安装 Python 便可分发

1.2 技术栈选型

层级 技术 说明
编程语言 Python 3.8+ 无需额外安装,Windows/macOS 均可使用
GUI 框架 Tkinter Python 自带标准库,零额外依赖
数据格式 JSON 轻量级文本格式,方便修改题库
打包工具 PyInstaller 将 Python 脚本打包为单个 EXE 文件

2. 环境准备与项目搭建

2.1 基础环境要求

  • Python 3.8 及以上版本(Tkinter 已内置,无需单独安装)
  • 任意文本编辑器(推荐 VS Code 或 PyCharm)
  • Windows 10/11 或 macOS 操作系统

2.2 确认 Tkinter 可用

打开终端或命令行,输入以下命令验证 Tkinter 是否可用。如果弹出一个空白小窗口,说明环境就绪:

# Windows PowerShell / CMD
python -m tkinter
或者进入 Python 交互环境测试
python -c "import tkinter; tkinter.Tk().mainloop()"

如果提示 ModuleNotFoundError: No module named '_tkinter',请重新安装 Python 并确保勾选“tcl/tk and IDLE”选项。

2.3 项目文件结构

新建项目文件夹 quiz_app,按以下结构组织文件:

quiz_app/
├── questions.json      # 题库文件(JSON 格式)
├── quiz_app.py          # 主程序入口
└── build/               # 打包输出目录(自动生成)

3. 题库设计:JSON 数据格式

题库以 JSON 格式存储,结构清晰易懂。每个题目包含题干、四个选项和正确答案索引。以下是一份示例题库,保存为 questions.json

[
    {
        "question": "Python 中用于定义函数的关键字是?",
        "options": ["func", "define", "def", "function"],
        "answer": 2
    },
    {
        "question": "Tkinter 是 Python 的什么库?",
        "options": ["数据分析库", "GUI 标准库", "网络请求库", "图像处理库"],
        "answer": 1
    },
    {
        "question": "以下哪个方法可以获取列表长度?",
        "options": ["length()", "size()", "count()", "len()"],
        "answer": 3
    },
    {
        "question": "Python 中哪个符号表示单行注释?",
        "options": ["//", "#", "/*", "--"],
        "answer": 1
    },
    {
        "question": "JSON 的全称是?",
        "options": [
            "Java Standard Object Notation",
            "JavaScript Object Notation",
            "Java Serialized Object Network",
            "JavaScript Online Network"
        ],
        "answer": 1
    }
]

字段说明:

  • question:题干文本
  • options:包含 4 个选项的列表
  • answer:正确答案的索引(从 0 开始),与 options 列表对应

4. 测验逻辑核心实现

在编写界面之前,先把测验的核心逻辑封装成一个独立类,便于后续和 GUI 层解耦。

import json
import time
class QuizEngine:
"""测验引擎:管理题目、计分、计时"""
def __init__(self, questions_file):
    with open(questions_file, "r", encoding="utf-8") as f:
        self.questions = json.load(f)
    self.total = len(self.questions)
    self.current_index = 0
    self.score = 0
    self.start_time = time.time()
def get_current_question(self):
"""返回当前题目数据,或 None(已完卷)"""
if self.current_index >= self.total:
return None
return self.questions[self.current_index]
def check_answer(self, user_choice):
"""判断用户选项是否正确,正确则加 1 分,同时移动到下一题"""
q = self.get_current_question()
if q is None:
return None
is_correct = (user_choice == q["answer"])
if is_correct:
self.score += 1
self.current_index += 1
return is_correct
def is_finished(self):
"""是否已完成全部题目"""
return self.current_index >= self.total
def get_progress(self):
"""返回 (当前题号, 总分, 正确数)"""
return self.current_index, self.total, self.score
def get_elapsed_time(self):
"""返回已用秒数"""
return int(time.time() - self.start_time)</code></pre>
这个引擎类把所有题目控制逻辑封装起来,不依赖任何界面细节,方便后续单独测试和复用。
5. 图形界面构建:Tkinter 窗口
5.1 主窗口骨架
首先创建程序入口和主窗口框架。窗口标题设为“AI 编程教育测验”,固定窗口尺寸并居中显示:
import tkinter as tk
from tkinter import messagebox
class QuizApp:
"""测验应用主窗口"""
def init(self, root, engine):
self.root = root
self.engine = engine
self.root.title("AI 编程教育测验")
self.root.geometry("700x500")
self.root.resizable(False, False)
# 如果使用 Python 3.8 以下版本,可能需要手动居中
self.root.eval("tk::PlaceWindow . center")
self.build_ui()
self.display_question()
def build_ui(self):
"""构建界面布局"""
# 标题标签
self.title_label = tk.Label(
self.root,
text="编程知识测验",
font=("Microsoft YaHei", 18, "bold"),
fg="#333333"
)
self.title_label.pack(pady=(20, 10))
# 分数 &amp;amp; 进度标签
self.status_label = tk.Label(
    self.root,
    text="",
    font=("Microsoft YaHei", 11),
    fg="#666666"
)
self.status_label.pack(pady=(0, 10))
题干显示区域
self.question_label = tk.Label(
self.root,
text="",
font=("Microsoft YaHei", 14),
wraplength=600,
justify="left",
fg="#222222"
)
self.question_label.pack(pady=(10, 20))
选项区域(使用 Radiobutton)
self.option_var = tk.IntVar(value=-1)  # -1 表示未选中
self.option_buttons = []
option_frame = tk.Frame(self.root)
option_frame.pack(pady=(0, 20))
for i in range(4):
btn = tk.Radiobutton(
option_frame,
text="",
variable=self.option_var,
value=i,
font=("Microsoft YaHei", 12),
anchor="w",
width=50,
indicatoron=True,
padx=10,
pady=4
)
btn.pack(fill="x", pady=3)
self.option_buttons.append(btn)
提交按钮
self.submit_btn = tk.Button(
self.root,
text="提交答案 →",
font=("Microsoft YaHei", 13, "bold"),
bg="#4A90D9",
fg="white",
activebackground="#357ABD",
activeforeground="white",
relief="flat",
padx=30,
pady=8,
cursor="hand2",
command=self.on_submit
)
self.submit_btn.pack(pady=(10, 20))&lt;/code&gt;&lt;/pre&gt;
5.2 题目展示与选项渲染
每次调用 display_question 方法都会从引擎获取当前题目数据,并更新界面上的题干文本和选项内容:
def display_question(self):
"""从引擎获取当前题目并渲染到界面"""
q = self.engine.get_current_question()
if q is None:
return
更新进度状态
idx, total, score = self.engine.get_progress()
self.status_label.config(text=f"第 {idx + 1}/{total} 题    |    已得分:{score} 分")
更新题干
self.question_label.config(text=q["question"])
更新选项
self.option_var.set(-1)
for i, btn in enumerate(self.option_buttons):
if i &amp;lt; len(q["options"]):
btn.config(text=q["options"][i], state="normal")
else:
btn.config(text="", state="disabled")&lt;/code&gt;&lt;/pre&gt;
5.3 提交答案与计分反馈
点击“提交答案”按钮后,程序会判断用户选择是否正确,弹出即时反馈弹窗,然后自动进入下一题或结束测验:
def on_submit(self):
"""处理提交答案事件"""
user_choice = self.option_var.get()
if user_choice == -1:
messagebox.showwarning("请选择", "请先选择一个答案再提交!")
return
is_correct = self.engine.check_answer(user_choice)
即时反馈
if is_correct:
feedback = "✓ 回答正确!加 1 分"
else:
q = self.engine.questions[self.engine.current_index - 1]
correct_option = q["options"][q["answer"]]
feedback = f"✗ 回答错误。正确答案是:{correct_option}"
messagebox.showinfo("结果", feedback)
判断是否结束
if self.engine.is_finished():
self.show_result()
else:
self.display_question()&lt;/code&gt;&lt;/pre&gt;
5.4 测验结果报告
全部题目作答完毕后,弹出成绩总结窗口,展示得分、正确率和用时:
def show_result(self):
"""显示测验结果报告"""
_, total, score = self.engine.get_progress()
elapsed = self.engine.get_elapsed_time()
percent = round(score / total * 100, 1)
result_text = (
f"测验结束!\n\n"
f"总题数:{total} 题\n"
f"正确数:{score} 题\n"
f"正确率:{percent}%\n"
f"用时:{elapsed} 秒\n\n"
)
if percent &amp;gt;= 80:
result_text += "🌟 很棒,继续保持!"
elif percent &amp;gt;= 60:
result_text += "👍 不错,再复习一下知识点吧!"
else:
result_text += "📚 需要加强学习,建议回顾相关课程。"
messagebox.showinfo("测验成绩单", result_text)
询问是否重新开始
if messagebox.askyesno("是否继续", "要重新开始测验吗?"):
self.root.destroy()  # 简易做法:关闭窗口后重新运行
else:
self.root.destroy()&lt;/code&gt;&lt;/pre&gt;
整合运行:入口代码
将上述所有代码整合到 quiz_app.py 的底部,添加程序入口:
if name == "main":
root = tk.Tk()
engine = QuizEngine("questions.json")
app = QuizApp(root, engine)
root.mainloop()
运行方式:
确保 questions.json 和 quiz_app.py 在同一目录下
终端执行:python quiz_app.py
窗口弹出后即可开始答题
打包为 EXE 文件
7.1 安装 PyInstaller
pip install pyinstaller
7.2 执行打包命令
在 quiz_app 目录下打开终端,执行以下命令:
基础打包(有命令行窗口)
pyinstaller --onefile --add-data "questions.json;." quiz_app.py
推荐:静默打包(无命令行窗口 + 自定义图标)
pyinstaller --onefile --windowed --add-data "questions.json;." --icon=app.ico --name "AI编程测验" quiz_app.py
参数说明:
--onefile:打包成单个 EXE 文件
--windowed:不显示命令行窗口(纯 GUI 运行)
--add-data:将 questions.json 打包进 EXE 内部
--icon:设置 EXE 图标(需要准备 .ico 格式图标文件)
--name:输出的 EXE 文件名
7.3 打包后适配 JSON 路径
打包成 EXE 后,questions.json 会被内置到临时目录。需要在 QuizEngine.init 中添加路径处理逻辑:
import os
import sys
def get_resource_path(relative_path):
"""获取资源文件的绝对路径,兼容开发环境和 EXE 打包环境"""
if getattr(sys, 'frozen', False):
PyInstaller 打包后的临时解压目录
base_dir = sys._MEIPASS
else:
base_dir = os.path.abspath(".")
return os.path.join(base_dir, relative_path)
class QuizEngine:
def init(self, questions_file):
file_path = get_resource_path(questions_file)
with open(file_path, "r", encoding="utf-8") as f:
self.questions = json.load(f)
... 其余初始化代码不变
7.4 打包产物
打包完成后,在 dist 目录下会生成单个 EXE 文件,大小约 10-20MB。将该 EXE 文件发送给任何人,无需安装 Python 即可直接运行。
8. 扩展建议
随机抽题:在 QuizEngine.init 中添加 random.shuffle(self.questions),每次测验顺序不同
错题回顾:收集错题,测验结束后展示错题列表和正确答案
多题库切换:通过下拉菜单或启动参数选择不同的 JSON 题库文件
计时压力模式:为每题添加倒计时,超时自动跳过
Excel 题库导入:支持从 .xlsx 文件批量导入题目,方便教师出题
9. 总结
本文从零开始,带你构建了一个完整、可直接运行的 Tkinter 教育测验软件。整个项目仅使用 Python 标准库,代码量约 150 行,结构清晰、易于修改和扩展。最后通过 PyInstaller 打包为单个 EXE,实现真正的“一次开发、零门槛分发”。无论是编程初学者还是教育工作者,都可以基于此模板快速制作适合自己的测验工具。
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐