import tkinter as tk from tkinter import ttk, messagebox, filedialog import json import random from datetime import datetime import os class ModernUIApp: def __init__(self, root): self.root = root self.root.title("托福单词默写系统") self.root.geometry("1000x700") self.root.configure(bg='#f0f0f0') # 设置现代化样式 self.setup_styles() # 创建主界面 self.create_main_interface() # 托福单词库(简化版) self.toefl_words = [ "abandon", "ability", "abnormal", "abolish", "abrupt", "absorb", "abstract", "abundant", "access", "accident", "accommodate", "accompany", "accomplish", "account", "accurate", "achieve", "acknowledge", "acquire", "adapt", "adequate", "adjust", "administer", "admire", "admit", "adopt", "advance", "advantage", "adventure", "advertise", "advise", "affect", "afford", "aggressive", "agree", "aid", "aim", "alert", "alien", "alike", "alive", "allocate", "allow", "ally", "alone", "alter", "alternative", "amateur", "amaze", "ambition", "amount", "ample", "analyze", "anchor", "ancient", "angle" ] self.selected_words = [] self.current_word_index = 0 self.mistakes = [] def setup_styles(self): # 配置样式 style = ttk.Style() style.theme_use('clam') # 自定义按钮样式 style.configure('Modern.TButton', padding=10, font=('Arial', 12, 'bold'), foreground='#ffffff', background='#4a90e2', borderwidth=0) style.map('Modern.TButton', background=[('active', '#357abd')]) # 自定义标签样式 style.configure('Title.TLabel', font=('Arial', 16, 'bold'), foreground='#2c3e50', background='#f0f0f0') style.configure('Subtitle.TLabel', font=('Arial', 12), foreground='#7f8c8d', background='#f0f0f0') def create_main_interface(self): # 创建主框架 main_frame = tk.Frame(self.root, bg='#f0f0f0') main_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=20) # 标题区域 title_frame = tk.Frame(main_frame, bg='#f0f0f0') title_frame.pack(fill=tk.X, pady=(0, 20)) title_label = ttk.Label(title_frame, text="托福单词默写系统", style='Title.TLabel') title_label.pack(side=tk.LEFT) # 模式选择区域 mode_frame = tk.Frame(main_frame, bg='#f0f0f0') mode_frame.pack(fill=tk.X, pady=(0, 20)) ttk.Label(mode_frame, text="选择使用模式:", style='Subtitle.TLabel').pack(side=tk.LEFT) self.teacher_btn = ttk.Button(mode_frame, text="老师端", style='Modern.TButton', command=self.show_teacher_interface) self.teacher_btn.pack(side=tk.LEFT, padx=(20, 10)) self.student_btn = ttk.Button(mode_frame, text="学生端", style='Modern.TButton', command=self.show_student_interface) self.student_btn.pack(side=tk.LEFT, padx=10) # 内容区域 self.content_frame = tk.Frame(main_frame, bg='#ffffff', relief=tk.RAISED, bd=1) self.content_frame.pack(fill=tk.BOTH, expand=True) # 显示欢迎界面 self.show_welcome_interface() def show_welcome_interface(self): self.clear_content_frame() welcome_frame = tk.Frame(self.content_frame, bg='#ffffff') welcome_frame.pack(expand=True) ttk.Label(welcome_frame, text="欢迎使用托福单词默写系统", font=('Arial', 18, 'bold'), foreground='#2c3e50', background='#ffffff').pack(pady=20) ttk.Label(welcome_frame, text="请选择您要使用的模式:老师端 或 学生端", font=('Arial', 12), foreground='#7f8c8d', background='#ffffff').pack(pady=10) def show_teacher_interface(self): self.clear_content_frame() # 创建笔记本控件用于选项卡 notebook = ttk.Notebook(self.content_frame) notebook.pack(fill=tk.BOTH, expand=True, padx=10, pady=10) # 单词选择页面 word_select_frame = tk.Frame(notebook, bg='#ffffff') notebook.add(word_select_frame, text="单词选择") self.create_word_selection_interface(word_select_frame) # 默写控制页面 dictation_frame = tk.Frame(notebook, bg='#ffffff') notebook.add(dictation_frame, text="开始默写") self.create_dictation_interface(dictation_frame) def create_word_selection_interface(self, parent): # 标题 ttk.Label(parent, text="选择托福单词", font=('Arial', 14, 'bold'), background='#ffffff').pack(pady=10) # 搜索框 search_frame = tk.Frame(parent, bg='#ffffff') search_frame.pack(fill=tk.X, padx=20, pady=10) ttk.Label(search_frame, text="搜索:", background='#ffffff').pack(side=tk.LEFT) self.search_var = tk.StringVar() search_entry = ttk.Entry(search_frame, textvariable=self.search_var, width=30) search_entry.pack(side=tk.LEFT, padx=10) search_entry.bind('', self.filter_words) # 单词列表框架 list_frame = tk.Frame(parent, bg='#ffffff') list_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=10) # 创建Treeview显示单词 columns = ('单词', '状态') self.word_tree = ttk.Treeview(list_frame, columns=columns, show='headings', height=15) # 设置列标题 self.word_tree.heading('单词', text='单词') self.word_tree.heading('状态', text='状态') self.word_tree.column('单词', width=200) self.word_tree.column('状态', width=100) # 滚动条 scrollbar = ttk.Scrollbar(list_frame, orient=tk.VERTICAL, command=self.word_tree.yview) self.word_tree.configure(yscrollcommand=scrollbar.set) self.word_tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True) scrollbar.pack(side=tk.RIGHT, fill=tk.Y) # 填充单词数据 self.populate_word_list() # 按钮区域 button_frame = tk.Frame(parent, bg='#ffffff') button_frame.pack(fill=tk.X, padx=20, pady=10) ttk.Button(button_frame, text="全选", style='Modern.TButton', command=self.select_all_words).pack(side=tk.LEFT, padx=5) ttk.Button(button_frame, text="取消全选", style='Modern.TButton', command=self.deselect_all_words).pack(side=tk.LEFT, padx=5) ttk.Button(button_frame, text="随机选择20个", style='Modern.TButton', command=self.random_select_words).pack(side=tk.LEFT, padx=5) ttk.Button(button_frame, text="导出配置文件", style='Modern.TButton', command=self.export_config).pack(side=tk.RIGHT, padx=5) # 统计信息 self.stats_label = ttk.Label(button_frame, text="已选择: 0 个单词", background='#ffffff') self.stats_label.pack(side=tk.RIGHT, padx=20) def populate_word_list(self): self.word_tree.delete(*self.word_tree.get_children()) for word in self.toefl_words: status = "✓ 已选择" if word in self.selected_words else "○ 未选择" self.word_tree.insert('', tk.END, values=(word, status)) def filter_words(self, event=None): # 简化的过滤功能 search_term = self.search_var.get().lower() if search_term: filtered_words = [word for word in self.toefl_words if search_term in word.lower()] else: filtered_words = self.toefl_words self.word_tree.delete(*self.word_tree.get_children()) for word in filtered_words: status = "✓ 已选择" if word in self.selected_words else "○ 未选择" self.word_tree.insert('', tk.END, values=(word, status)) def select_all_words(self): self.selected_words = self.toefl_words.copy() self.populate_word_list() self.update_stats() def deselect_all_words(self): self.selected_words = [] self.populate_word_list() self.update_stats() def random_select_words(self): self.selected_words = random.sample(self.toefl_words, min(20, len(self.toefl_words))) self.populate_word_list() self.update_stats() def update_stats(self): self.stats_label.config(text=f"已选择: {len(self.selected_words)} 个单词") def export_config(self): if not self.selected_words: messagebox.showwarning("警告", "请先选择单词!") return filename = filedialog.asksaveasfilename( defaultextension=".json", filetypes=[("JSON files", "*.json"), ("All files", "*.*")], title="保存配置文件" ) if filename: config = { "words": self.selected_words, "created_time": datetime.now().isoformat(), "version": "1.0" } try: with open(filename, 'w', encoding='utf-8') as f: json.dump(config, f, ensure_ascii=False, indent=2) messagebox.showinfo("成功", f"配置文件已保存到:\n{filename}") except Exception as e: messagebox.showerror("错误", f"保存失败: {str(e)}") def show_student_interface(self): self.clear_content_frame() # 标题 ttk.Label(self.content_frame, text="学生端 - 导入配置", font=('Arial', 14, 'bold'), background='#ffffff').pack(pady=20) # 导入区域 import_frame = tk.Frame(self.content_frame, bg='#ffffff') import_frame.pack(fill=tk.BOTH, expand=True, padx=50, pady=20) ttk.Label(import_frame, text="请导入老师端生成的配置文件", font=('Arial', 12), background='#ffffff').pack(pady=10) ttk.Button(import_frame, text="选择配置文件", style='Modern.TButton', command=self.import_config).pack(pady=20) # 显示导入的单词信息 self.word_info_label = ttk.Label(import_frame, text="尚未导入配置文件", font=('Arial', 10), background='#ffffff') self.word_info_label.pack(pady=10) def import_config(self): filename = filedialog.askopenfilename( filetypes=[("JSON files", "*.json"), ("All files", "*.*")], title="选择配置文件" ) if filename: try: with open(filename, 'r', encoding='utf-8') as f: config = json.load(f) self.selected_words = config.get('words', []) created_time = config.get('created_time', '未知') self.word_info_label.config( text=f"已导入 {len(self.selected_words)} 个单词\n创建时间: {created_time}" ) messagebox.showinfo("成功", f"成功导入 {len(self.selected_words)} 个单词!") except Exception as e: messagebox.showerror("错误", f"导入失败: {str(e)}") def create_dictation_interface(self, parent): # 标题 ttk.Label(parent, text="开始默写", font=('Arial', 14, 'bold'), background='#ffffff').pack(pady=10) # 控制按钮 control_frame = tk.Frame(parent, bg='#ffffff') control_frame.pack(fill=tk.X, padx=20, pady=10) ttk.Button(control_frame, text="开始默写", style='Modern.TButton', command=self.start_dictation).pack(side=tk.LEFT, padx=5) ttk.Button(control_frame, text="暂停", style='Modern.TButton', command=self.pause_dictation).pack(side=tk.LEFT, padx=5) ttk.Button(control_frame, text="结束", style='Modern.TButton', command=self.end_dictation).pack(side=tk.LEFT, padx=5) # 默写显示区域 dictation_frame = tk.Frame(parent, bg='#ffffff') dictation_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=10) # 当前单词显示 self.current_word_label = ttk.Label(dictation_frame, text="点击'开始默写'开始", font=('Arial', 24, 'bold'), background='#ffffff') self.current_word_label.pack(expand=True) # 进度信息 self.progress_label = ttk.Label(dictation_frame, text="进度: 0/0", font=('Arial', 12), background='#ffffff') self.progress_label.pack(pady=10) def start_dictation(self): if not self.selected_words: messagebox.showwarning("警告", "请先在'单词选择'页面选择单词!") return self.current_word_index = 0 self.mistakes = [] self.show_next_word() def show_next_word(self): if self.current_word_index < len(self.selected_words): word = self.selected_words[self.current_word_index] self.current_word_label.config(text=word) self.progress_label.config( text=f"进度: {self.current_word_index + 1}/{len(self.selected_words)}" ) else: self.end_dictation() def pause_dictation(self): messagebox.showinfo("暂停", "默写已暂停") def end_dictation(self): self.current_word_label.config(text="默写结束") self.progress_label.config(text=f"完成: {len(self.selected_words)}/{len(self.selected_words)}") messagebox.showinfo("完成", f"默写完成!共 {len(self.selected_words)} 个单词") def clear_content_frame(self): for widget in self.content_frame.winfo_children(): widget.destroy() def main(): root = tk.Tk() app = ModernUIApp(root) root.mainloop() if __name__ == "__main__": main()