WordCard 技术文档
版本:1.0
简介
WordClock 是基于 customtkinter 的桌面小工具,用于在桌面悬浮窗中循环显示单词及其翻译,并支持从 JSON 导入词表、将词表写入 SQLite 数据库、通过系统托盘控制程序、保存窗口位置及设置等功能。
主要特点:
- 悬浮、圆角、透明窗口,常驻桌面并支持拖动和隐藏到托盘。
- 自动按间隔随机切换单词并更新 UI。
- 支持将 JSON 词表导入到 SQLite 并作为可选词表使用。
- 支持通过设置窗口管理词表、设置切换间隔、删除词表与制作 JSON 文件。
- 使用多线程处理长耗时操作(导入、加载词表、托盘)以保证 UI 不阻塞。
快速开始
- 安装依赖(示例):
|
|
注意:
customtkinter依赖tkinter(通常随 Python 自带),若缺少请安装对应系统包。
- 将代码保存为
word_clock.py,并确保同目录下有单词.db(或指定其他路径)。 - 运行:
|
|
- 第一次运行会生成
settings.json(默认 intervaltime = 5 秒),可在设置窗口调整。
环境依赖
- Python 3.8+
- tkinter(GUI)
- customtkinter
- pystray
- pillow (PIL)
- sqlite3(Python 标准库)
平台注意:代码中使用了 Windows 特定的 Win32 API(通过 ctypes)来隐藏任务栏图标,因此最佳运行环境为 Windows。在非 Windows 系统上应移除或条件兼容该部分。
文件结构
假设单文件项目:
|
|
导入的 JSON 文件示例(每个元素为对象):
|
|
主要类与方法说明
WordClock (继承自 ctk.CTk)
描述:应用的主窗口类,封装 UI、数据库连接、托盘、线程与设置保存。
属性(重要)
SETTINGS_FILE:字符串,默认settings.json。db_path:SQLite 数据库路径,默认单词.db。db_conn,db_cursor:数据库连接与游标(持久连接,check_same_thread=False)。wordtables:从 SQLite 读取到的表名列表。words_list:当前选中词表对应的单词列表,元素为(word, translate)。intervaltime:单词切换时间间隔(秒)。running:布尔,控制自动更新线程运行。loading:布尔,指示是否处于词表加载中,用于暂停自动刷新。
方法摘要(按功能分组)
- 初始化与窗口配置
__init__(self, db_path="单词.db"):创建窗口、加载配置、打开数据库连接、启动托盘线程与自动刷新线程、绑定关闭事件等。hide_from_taskbar(self):使用ctypes调用 Win32 API 将窗口从任务栏隐藏(Windows-specific)。bind_drag_events(self)、start_drag、on_drag:支持拖动并在拖动时保存位置。
- 设置存取
load_settings(self):读取settings.json,若不存在返回默认配置。save_settings(self):保存窗口位置、当前选表名、间隔等到settings.json。on_close(self):窗口关闭回调,保存设置并退出。
- 数据库与数据加载
fetch_wordtables(self, db_path):读取 SQLite 中的表名并存入self.wordtables。SQL 为SELECT name FROM sqlite_master WHERE type='table' ORDER BY rowid;。load_words_from_db(self, db_path, table_name=None):读取指定表的word, translate列并返回列表;若未传表名,默认取self.wordtables[0]。json2sqldb(self, file_address, file_name):将 JSON 数据写入新建的 SQLite 表,包含事务优化(调整 PRAGMA、BEGIN TRANSACTION、executemany、commit),最后恢复 PRAGMA 设置。
- 自动切换与UI更新
auto_update_words(self):后台线程循环,根据self.intervaltime随机选择单词并通过after(0, ...)回到主线程更新 UI。会在self.loading=True时短暂等待以避免冲突。display_translation(self, text):当翻译过长时设置wraplength以换行显示。
- 托盘相关
setup_tray(self):构造托盘图标与菜单(显示/隐藏、设置、退出),并运行事件循环(pystray)。独立线程运行。toggle_window(self, icon=None, item=None):切换窗口显示/隐藏。quit_app(self, icon=None, item=None):停止线程、关闭数据库并退出。
- 设置窗口与词表管理
so_setting(self):打开设置窗口,构建左侧控制按钮与右侧显示词表的滚动区域,并异步加载表名。load_wordtables_async(self):后台加载表并回调put_tables_on_right。put_tables_on_right(self):基于self.wordtables在滚动区构建按钮并支持高亮当前表。on_label_click_with_confirmation(self, name, button):点击某个词表按钮弹出确认框,确认后显示遮罩并在后台加载数据,加载完成后更新 UI 与当前表。del_wordtable(self)/confirm_delete(self, table_name, popup):删除选中表并刷新 UI。open_make_wordtable_window(self)/generate_json_from_text(self, text_box, win):允许用户粘贴文本快速生成 JSON 文件(每行单词 翻译),并保存 JSON。
- 加载遮罩与动画
_create_loading_overlay(self, message="正在加载…"):在main_frame上创建覆盖层(遮罩)并返回 overlay。_start_loading_animation(self, overlay):使用after循环更新点点动画,直至self.loading=False。_stop_loading_animation(self):取消动画任务。
- 辅助弹窗
show_popup(self, message: str, duration: int = 1800):自定义CTkToplevel弹窗,代替未加载的CTkMessagebox。
数据库与数据格式
- SQLite 表结构(在
json2sqldb创建)
|
|
- JSON 导入格式:数组,每项为对象:
{"word": "xxx", "translate": "yyy"}。 - 注意:代码假设表中存在
word与translate字段。若你的原始表结构不同,需修改load_words_from_db查询语句。
设置与持久化(settings.json)
settings.json 存储字段:
pos_x、pos_y:上次窗口位置(像素坐标)。last_table:上次使用的词表名。intervaltime:单词自动切换间隔(秒)。
默认文件会在程序首次运行时创建(intervaltime=5)。保存由 save_settings() 完成(拖动、修改间隔、关闭时等触发)。
运行与调试建议
- 数据库无法连接:确认
db_path路径正确且文件存在。若数据库为空,程序的fetch_wordtables可能返回空列表,load_words_from_db会返回占位("No word","无")。 - 线程安全:使用了
sqlite3.connect(..., check_same_thread=False)来允许多线程访问。但推荐仅主线程使用游标并在子线程使用新的连接(sqlite3.connect(self.db_path))以避免潜在竞态。 - 托盘图标不显示或程序无反应:
pystray在某些平台或环境需要额外配置。测试时可先注释setup_tray并直接运行主窗口检查 UI。 - 隐藏任务栏仅在 Windows 生效:
hide_from_taskbar()使用 Win32 API,仅在 Windows 上有效,跨平台请条件判断或移除。 - 日志与异常:建议扩展
print为logging模块,并在关键异常中记录堆栈信息以便排查。
常见问题与解决方法
- 问:窗口没有显示单词或只显示
No word。- 因为数据库中没有表或表中没有数据。确保通过导入 JSON 创建了至少一个表或手动向 SQLite 中插入数据。
- 问:点击词表按钮没反应。
- 检查
word_table_buttons是否正确生成,以及self.wordtables是否有数据。
- 检查
- 问:应用未隐藏到系统托盘或无法退出。
- 检查
pystray是否正常安装并且在当前平台支持托盘操作。临时方法:直接关闭窗口或在代码中调用quit_app()。
- 检查
扩展与改进建议
- 使用线程池/Executor:替换原始
threading.Thread为concurrent.futures.ThreadPoolExecutor以更好地管理线程生命周期与异常捕获。 - 数据库连接策略:将长期持久连接改为“按线程新建连接”的策略(每个线程独立连接),以避免跨线程共享同一游标导致的问题。
- UI 优化:为长文本增加动效、增加单词发音(调用 TTS 或在线 API)、支持多语言界面切换。
- 配置界面改进:在设置窗口直接显示并编辑
intervaltime,支持导入 CSV、 Excel;提供词表导出功能(JSON / CSV)。 - 跨平台兼容:为
hide_from_taskbar添加平台判断,并实现 macOS / Linux 下替代实现或跳过该功能。 - 错误日志:集成日志文件输出以及可选的错误上报(不建议在个人项目中默认开启)。
附:典型 JSON 输入示例
|
|