Python + Tkinter + pyttsx3实现的桌面版英语学习工具
Python + Tkinter + pyttsx3实现的桌面版英语学习工具
在多行文本框输入英文句子,双击其中的英文单词,给出英文读音和中文含义和音标。
本程序查询本地词典数据。通过菜单栏"文件"->"打开词典编辑器"进入编辑界面。
词典数据存储在独立的dictionary.json文件中,这个文件需要和程序文件在同一文件夹中,否则将自动建立一个。
编辑器实现了完整的CRUD(创建、读取、更新、删除)功能
添加单词:直接填写所有字段后点击"添加单词"
编辑单词:从列表选择单词 -> 修改字段 -> 点击"保存修改"
删除单词:从列表选择单词 -> 点击"删除选中"
pyttsx3 是一个文本到语音(Text-to-Speech, TTS)转换库,它允许你在 Python 程序中将文本转换为语音输出。它是第三方库需要安装使用。
在cmd中,使用 Python 包安装命令安装:pip install pyttsx3
若安装了多个python版本,X.Y代表Python版本,多余的部分舍弃如3.8.1取3.8,3.10.5取3.10,即只取第二个点前的部分。仅安装了一个python版本不需要。pip命令默认会连接在国外的python官方服务器下载,速度可能比较慢,使用镜像网址可以加快速度:-i 镜像网址
py -3.12 -m pip install 第三方库名 -i https://pypi.tuna.tsinghua.edu.cn/simple
py -3.12 -m pip install pyttsx3 -i https://pypi.tuna.tsinghua.edu.cn/simple
运行效果:

源码如下:
import tkinter as tk
from tkinter import ttk, messagebox, simpledialog
import json
import os
import pyttsx3class DictionaryEditor:def __init__(self, master, dictionary, save_callback):self.master = masterself.dictionary = dictionaryself.save_callback = save_callbackself.selected_word = Nonemaster.title("词典编辑器")master.geometry("600x400")# 创建界面组件self.create_widgets()self.update_word_list()def create_widgets(self):# 单词列表框架list_frame = ttk.Frame(self.master)list_frame.pack(side=tk.LEFT, padx=10, pady=10, fill=tk.BOTH, expand=True)self.word_list = tk.Listbox(list_frame, selectmode=tk.SINGLE)self.word_list.pack(fill=tk.BOTH, expand=True)self.word_list.bind('<<ListboxSelect>>', self.on_word_select)# 控制按钮框架btn_frame = ttk.Frame(list_frame)btn_frame.pack(pady=5)ttk.Button(btn_frame, text="刷新列表", command=self.update_word_list).pack(side=tk.LEFT, padx=2)ttk.Button(btn_frame, text="删除选中", command=self.delete_word).pack(side=tk.LEFT, padx=2)# 编辑区框架edit_frame = ttk.Frame(self.master)edit_frame.pack(side=tk.RIGHT, padx=10, pady=10, fill=tk.BOTH, expand=True)# 输入字段ttk.Label(edit_frame, text="单词:").grid(row=0, column=0, sticky=tk.W)self.word_entry = ttk.Entry(edit_frame)self.word_entry.grid(row=0, column=1, pady=5, sticky=tk.EW)ttk.Label(edit_frame, text="音标:").grid(row=1, column=0, sticky=tk.W)self.phonetic_entry = ttk.Entry(edit_frame)self.phonetic_entry.grid(row=1, column=1, pady=5, sticky=tk.EW)ttk.Label(edit_frame, text="翻译:").grid(row=2, column=0, sticky=tk.W)self.translation_entry = ttk.Entry(edit_frame)self.translation_entry.grid(row=2, column=1, pady=5, sticky=tk.EW)# 操作按钮btn_frame = ttk.Frame(edit_frame)btn_frame.grid(row=3, column=0, columnspan=2, pady=10)ttk.Button(btn_frame, text="添加单词", command=self.add_word).pack(side=tk.LEFT, padx=5)ttk.Button(btn_frame, text="保存修改", command=self.save_changes).pack(side=tk.LEFT, padx=5)def update_word_list(self):self.word_list.delete(0, tk.END)for word in sorted(self.dictionary.keys()):self.word_list.insert(tk.END, word)def on_word_select(self, event):selection = self.word_list.curselection()if selection:self.selected_word = self.word_list.get(selection[0])self.load_word_data()def load_word_data(self):data = self.dictionary.get(self.selected_word, {})self.word_entry.delete(0, tk.END)self.phonetic_entry.delete(0, tk.END)self.translation_entry.delete(0, tk.END)self.word_entry.insert(0, self.selected_word)self.phonetic_entry.insert(0, data.get('phonetic', ''))self.translation_entry.insert(0, data.get('translation', ''))def validate_input(self):word = self.word_entry.get().strip().lower()phonetic = self.phonetic_entry.get().strip()translation = self.translation_entry.get().strip()if not word:messagebox.showwarning("输入错误", "单词不能为空")return Falseif not translation:messagebox.showwarning("输入错误", "翻译不能为空")return Falsereturn Truedef add_word(self):if not self.validate_input():returnnew_word = self.word_entry.get().strip().lower()if new_word in self.dictionary:messagebox.showwarning("添加失败", "该单词已存在")returnself.dictionary[new_word] = {'phonetic': self.phonetic_entry.get().strip(),'translation': self.translation_entry.get().strip()}self.save_data()self.update_word_list()messagebox.showinfo("成功", "单词已添加")def save_changes(self):if not self.selected_word or not self.validate_input():returnnew_word = self.word_entry.get().strip().lower()# 检查是否修改了单词if new_word != self.selected_word:if new_word in self.dictionary:messagebox.showwarning("修改失败", "目标单词已存在")return# 删除旧条目并创建新条目del self.dictionary[self.selected_word]self.selected_word = new_wordself.dictionary[new_word] = {'phonetic': self.phonetic_entry.get().strip(),'translation': self.translation_entry.get().strip()}self.save_data()self.update_word_list()messagebox.showinfo("成功", "修改已保存")def delete_word(self):if not self.selected_word:returnif messagebox.askyesno("确认删除", f"确定要删除 '{self.selected_word}' 吗?"):del self.dictionary[self.selected_word]self.save_data()self.selected_word = Noneself.update_word_list()messagebox.showinfo("成功", "单词已删除")def save_data(self):self.save_callback()class EnglishLearningApp:def __init__(self, master):self.master = mastermaster.title("英语学习助手")master.geometry("800x600")# 初始化语音引擎self.engine = pyttsx3.init()self.engine.setProperty('rate', 150)# 创建菜单self.create_menu()# 加载词典数据self.dictionary_file = "dictionary.json"self.dictionary = self.load_dictionary()# 创建界面组件self.create_widgets()# 添加缺失的 load_dictionary 方法def load_dictionary(self):"""从JSON文件加载词典数据"""try:if not os.path.exists(self.dictionary_file):# 如果文件不存在,创建默认词典default_data = {"hello": {"translation": "你好", "phonetic": "/həˈloʊ/"},"world": {"translation": "世界", "phonetic": "/wɜːrld/"}}with open(self.dictionary_file, 'w', encoding='utf-8') as f:json.dump(default_data, f, indent=2, ensure_ascii=False)return default_datawith open(self.dictionary_file, 'r', encoding='utf-8') as f:data = json.load(f)# 验证数据格式if not all(['translation' in v and 'phonetic' in v for v in data.values()]):raise ValueError("词典文件格式不正确")return dataexcept Exception as e:messagebox.showerror("初始化错误", f"无法加载词典:{str(e)}")self.master.destroy()  # 关闭程序exit(1)def create_widgets(self):# 输入文本框self.text_input = tk.Text(self.master,height=10,wrap=tk.WORD,font=('Arial', 12),borderwidth=2,relief="groove")self.text_input.pack(pady=10, padx=20, fill=tk.BOTH, expand=True)self.text_input.bind("<Double-Button-1>", self.on_double_click)# 结果显示区域self.result_frame = ttk.Frame(self.master)self.result_frame.pack(pady=10, padx=20, fill=tk.BOTH, expand=True)self.result_label = ttk.Label(self.result_frame,text="双击单词,出现查询结果:",font=('Arial', 12, 'bold'))self.result_label.pack(anchor=tk.W)self.result_text = tk.Text(self.result_frame,height=6,wrap=tk.WORD,font=('Arial', 12),bg='#f0f8ff',borderwidth=2,relief="groove")self.result_text.pack(fill=tk.BOTH, expand=True)# 发音按钮self.speak_button = ttk.Button(self.master,text="播放发音",command=self.speak_word)self.speak_button.pack(pady=5)def on_double_click(self, event):try:# 获取选中的单词self.text_input.tag_remove("sel", "1.0", tk.END)self.text_input.tag_add("sel", "current wordstart", "current wordend")selected_word = self.text_input.get("sel.first", "sel.last").lower()if selected_word:# 查询词典result = self.dictionary.get(selected_word)if result:self.show_result(selected_word, result)self.current_word = selected_wordelse:self.result_text.delete(1.0, tk.END)self.result_text.insert(tk.END, f"未找到 '{selected_word}' 的释义")except Exception as e:messagebox.showerror("错误", f"发生错误:{str(e)}")def show_result(self, word, data):self.result_text.config(state=tk.NORMAL)self.result_text.delete(1.0, tk.END)result_str = (f"单词:{word}\n\n"f"音标:{data['phonetic']}\n\n"f"中文释义:{data['translation']}")self.result_text.insert(tk.END, result_str)self.result_text.config(state=tk.DISABLED)def speak_word(self):if hasattr(self, 'current_word'):self.engine.say(self.current_word)self.engine.runAndWait()        def create_menu(self):menubar = tk.Menu(self.master)# 文件菜单file_menu = tk.Menu(menubar, tearoff=0)file_menu.add_command(label="打开词典编辑器", command=self.open_editor)file_menu.add_separator()file_menu.add_command(label="退出", command=self.master.destroy) menubar.add_cascade(label="文件", menu=file_menu)self.master.config(menu=menubar)def open_editor(self):editor_window = tk.Toplevel(self.master)DictionaryEditor(editor_window, self.dictionary, self.save_dictionary)def save_dictionary(self):try:with open(self.dictionary_file, 'w', encoding='utf-8') as f:json.dump(self.dictionary, f, indent=2, ensure_ascii=False)except Exception as e:messagebox.showerror("保存失败", f"无法保存词典文件:{str(e)}")if __name__ == "__main__":root = tk.Tk()app = EnglishLearningApp(root)root.mainloop()
 
相关文章:
Python + Tkinter + pyttsx3实现的桌面版英语学习工具
Python Tkinter pyttsx3实现的桌面版英语学习工具 在多行文本框输入英文句子,双击其中的英文单词,给出英文读音和中文含义和音标。 本程序查询本地词典数据。通过菜单栏"文件"->"打开词典编辑器"进入编辑界面。 词典数据存储…...
【Vite + Vue + Ts 项目三个 tsconfig 文件】
Vite Vue Ts 项目三个 tsconfig 文件 为什么 Vite Vue Ts 项目会有三个 tsconfig 文件?首先我们先了解什么是 tsconfig.json ? 为什么 Vite Vue Ts 项目会有三个 tsconfig 文件? 在使用 Vite 创建 vue-ts 模板的项目时,会发现除了 ts…...
AI时代IT行业职业方向规划大纲
一、引言 AI时代的颠覆性影响 ChatGPT、Midjourney等生成式AI对传统工作模式的冲击 案例:AI编程助手(GitHub Copilot)改变开发者工作流程 核心问题:IT从业者如何避免被AI替代,并找到新机遇? 二、AI时代…...
Mac M1 Comfyui 使用MMAudio遇到的问题解决?
问题1: AssertionError: Torch not compiled with CUDA enabled? 解决办法:修改代码以 CPU 运行 第一步:找到 /ComfyUI/custom_nodes/ComfyUI-MMAudio/mmaudio/ext/autoencoder/vae.py文件中的下面这两行代码 self.data_mean nn.Buffer(t…...
大语言模型深度研究功能:人类认知与创新的新范式
在人工智能迅猛发展的今天,大语言模型(LLM)的深度研究功能正在成为重塑人类认知方式的关键力量。这一突破性技术不仅带来了工具层面的革新,更深刻地触及了人类认知能力的本质。本文将从认知科学的角度出发,探讨LLM如何…...
[SAP ABAP] 性能优化
1.数据库编程OPEN SQL方面优化 1.避免使用SELECT *,只查询需要的字段即可 尽量使用SELECT f1 f2 ... (具体字段) 来代替 SELECT * 写法 2. 如果确定只查询一条数据时,使用 SELECT SINGLE... 或者是 SELECT ...UP TO 1 ROWS ... 使用语法 UP TO n ROWS 来…...
并行计算、分布式计算与云计算:概念剖析与对比研究(表格对比)
什么是并行计算?什么是分布计算?什么是云计算?我们如何更好理解这3个概念,我们采用概念之间的区别和联系的方式来理解,做到切实理解,深刻体会。 1、并行计算与分布式计算 并行计算、分布式计算都属于高性…...
ASP.NET Core Filter
目录 什么是Filter? Exception Filter 实现 注意 ActionFilter 注意 案例:自动启用事务的筛选器 事务的使用 TransactionScopeFilter的使用 什么是Filter? 切面编程机制,在ASP.NET Core特定的位置执行我们自定义的代码。…...
doris:删除操作概述
在 Apache Doris 中,删除操作(Delete)是一项关键功能,用于管理和清理数据,以满足用户在大规模数据分析场景中的灵活性需求。 Doris 提供了丰富多样的删除功能支持,包括:DELETE 语句、删除标记&…...
【思维导图】redis
学习计划:将目前已经学的知识点串成一个思维导图。在往后的学习过程中,不断往思维导图里补充,形成自己整个知识体系。对于思维导图里的每个技术知识,自己用简洁的话概括出来, 训练自己的表达能力。...
申博经验贴
1. 所谓申博,最重要的就是定制的海投 分成两个部分 1. 定制 要根据每个教授去写不同的,一定不要泛泛的去写,一定要非常非常的具体,要引起教授的兴趣。每个教授每天都会收到几十封邮件,所以要足够的引起教授的注意&a…...
.Net Core笔记知识点(跨域、缓存)
设置前端跨域配置示例: builder.Services.AddCors(option > {option.AddDefaultPolicy(policy > {policy.WithOrigins(originUrls).AllowAnyMethod().AllowAnyHeader().AllowCredentials();});});var app builder.Build();app.UseCors(); 【客户端缓存】接…...
YOLOV11-1:YoloV11-安装和CLI方式训练模型
YoloV11-安装和CLI方式训练模型 1.安装和运行1.1安装的基础环境1.2安装yolo相关组件1.3命令行方式使用1.3.1 训练1.3.2 预测 本文介绍yoloV11的安装和命令行接口 1.安装和运行 1.1安装的基础环境 GPU环境,其中CUDA是12.4版本 1.2安装yolo相关组件 # 克隆github…...
自学习记录-编程语言的特点(持续记录)
我学习的顺序是C -> python -> C -> Java。在讲到某项语言的特点是,可能会时不时穿插其他语言的特点。 Java 1 注解Annotation Python中也有类似的Decorators。以下为AI学习了解到的: Java的Annotation是一种元数据(metadata)&a…...
TypeScript (TS) 和 JavaScript (JS)
TypeScript (TS) 和 JavaScript (JS) 的区别主要在于 TypeScript 是 JavaScript 的一个超集,它在 JavaScript 基础上增加了类型系统和一些高级功能。让我们详细看看两者的区别和关系: 类型系统: TypeScript 最大的特点是 静态类型。在 TypeSc…...
【HarmonyOS之旅】基于ArkTS开发(二) -> UI开发三
目录 1 -> 绘制图形 1.1 -> 绘制基本几何图形 1.2 -> 绘制自定义几何图形 2 -> 添加动画效果 2.1 -> animateTo实现闪屏动画 2.2 -> 页面转场动画 3 -> 常见组件说明 1 -> 绘制图形 绘制能力主要是通过框架提供的绘制组件来支撑,支…...
如何选择Spring AOP的动态代理?JDK与CGLIB的适用场景?
在Spring AOP中,选择JDK动态代理还是CGLIB动态代理取决于目标对象的特性以及具体需求。以下是两种代理方式的适用场景和特点: JDK动态代理 • 适用场景: • 目标对象实现了接口:JDK动态代理要求目标对象必须实现至少一个接口&a…...
手机连接WIFI可以上网,笔记本电脑连接WIFI却不能上网? 解决方法?
原因:DNS受污染了 解决办法 step 1:清空域名解析记录(清空DNS) ipconfig /flushdns (Windows cmd命令行输入) step 2:重新从DHCP 获取IP ipconfig /release(释放当前IP地址) ipconfig /renew &…...
MySQL不适合创建索引的11种情况
文章目录 前言1. **数据量小的表**2. **频繁更新的列**3. **低选择性的列**4. **频繁插入和删除的表**5. **查询中很少使用的列**6. **大文本或BLOB列**7. **复合索引中未使用的前导列**8. **频繁进行批量插入的表**9. **查询返回大部分数据的表**10. **临时表**11. **列值频繁…...
树莓派pico入坑笔记,故障解决:请求 USB 设备描述符失败,故障码(43)
今天心血来潮,拿出吃灰的pico把玩一下,打开thonny,上电,然后...... 上电识别不到端口,windows报错,请求 USB 设备描述符失败,故障码(43) 一开始以为是坏了(磕…...
华为云AI开发平台ModelArts
华为云ModelArts:重塑AI开发流程的“智能引擎”与“创新加速器”! 在人工智能浪潮席卷全球的2025年,企业拥抱AI的意愿空前高涨,但技术门槛高、流程复杂、资源投入巨大的现实,却让许多创新构想止步于实验室。数据科学家…...
Cursor实现用excel数据填充word模版的方法
cursor主页:https://www.cursor.com/ 任务目标:把excel格式的数据里的单元格,按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例,…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序
一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...
安卓基础(aar)
重新设置java21的环境,临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的: MyApp/ ├── app/ …...
淘宝扭蛋机小程序系统开发:打造互动性强的购物平台
淘宝扭蛋机小程序系统的开发,旨在打造一个互动性强的购物平台,让用户在购物的同时,能够享受到更多的乐趣和惊喜。 淘宝扭蛋机小程序系统拥有丰富的互动功能。用户可以通过虚拟摇杆操作扭蛋机,实现旋转、抽拉等动作,增…...
解析奥地利 XARION激光超声检测系统:无膜光学麦克风 + 无耦合剂的技术协同优势及多元应用
在工业制造领域,无损检测(NDT)的精度与效率直接影响产品质量与生产安全。奥地利 XARION开发的激光超声精密检测系统,以非接触式光学麦克风技术为核心,打破传统检测瓶颈,为半导体、航空航天、汽车制造等行业提供了高灵敏…...
DBLP数据库是什么?
DBLP(Digital Bibliography & Library Project)Computer Science Bibliography是全球著名的计算机科学出版物的开放书目数据库。DBLP所收录的期刊和会议论文质量较高,数据库文献更新速度很快,很好地反映了国际计算机科学学术研…...
Python竞赛环境搭建全攻略
Python环境搭建竞赛技术文章大纲 竞赛背景与意义 竞赛的目的与价值Python在竞赛中的应用场景环境搭建对竞赛效率的影响 竞赛环境需求分析 常见竞赛类型(算法、数据分析、机器学习等)不同竞赛对Python版本及库的要求硬件与操作系统的兼容性问题 Pyth…...
MySQL的pymysql操作
本章是MySQL的最后一章,MySQL到此完结,下一站Hadoop!!! 这章很简单,完整代码在最后,详细讲解之前python课程里面也有,感兴趣的可以往前找一下 一、查询操作 我们需要打开pycharm …...
PH热榜 | 2025-06-08
1. Thiings 标语:一套超过1900个免费AI生成的3D图标集合 介绍:Thiings是一个不断扩展的免费AI生成3D图标库,目前已有超过1900个图标。你可以按照主题浏览,生成自己的图标,或者下载整个图标集。所有图标都可以在个人或…...
