import tkinter as tk
from tkinter import ttk, messagebox, scrolledtext, filedialog, colorchooser
import time
import random
import json
import os
from datetime import datetime
import csv
from PIL import Image, ImageTk
import math


class TypingPracticeApp:
    def __init__(self):
        # 主窗口
        self.main_window = tk.Tk()
        self.main_window.title("打字练习 v2.0")
        self.main_window.geometry("900x700")

        # 设置图标
        self.set_window_icon()

        # 数据文件
        self.data_file = "typing_data.json"
        self.history_file = "typing_history.csv"

        # 状态变量
        self.current_text = ""
        self.start_time = None
        self.is_typing = False
        self.is_paused = False
        self.pause_start = None
        self.pause_time = 0
        self.timer_id = None

        # 用户设置
        self.settings = {
            "font_size": 14,
            "theme": "light",
            "difficulty": "medium",
            "show_timer": True,
            "sound_effects": True,
            "auto_save": True
        }

        # 文本库
        self.text_library = self.load_text_library()

        # 练习统计
        self.session_stats = {
            "total_chars": 0,
            "correct_chars": 0,
            "total_time": 0,
            "exercises_completed": 0
        }

        # 子窗口引用
        self.settings_window = None
        self.stats_window = None
        self.help_window = None
        self.search_window = None

        # 加载数据
        self.load_settings()
        self.load_user_data()

        # 创建界面
        self.setup_main_window()

        # 启动
        self.load_random_text()
        self.main_window.mainloop()

    def set_window_icon(self):
        """设置窗口图标"""
        try:
            # 尝试加载图标文件
            icon_path = "typing_icon.ico"
            if os.path.exists(icon_path):
                self.main_window.iconbitmap(icon_path)
        except:
            # 如果图标文件不存在，使用默认图标
            pass

    def load_text_library(self):
        """加载文本库"""
        return {
            "入门级": [
                "The quick brown fox jumps over the lazy dog.",
                "Hello world! This is a typing practice software.",
                "Python is easy to learn and powerful.",
                "Practice makes perfect. Keep typing!",
                "Good typing skills are important for programmers."
            ],
            "初级": [
                "The early bird catches the worm, but the second mouse gets the cheese.",
                "Learning to type quickly and accurately takes time and practice.",
                "Programming is not about typing, but typing well helps a lot.",
                "Consistent practice is the key to becoming a proficient typist.",
                "Every great typist started as a beginner with slow fingers."
            ],
            "中级": [
                "Python's simplicity allows developers to write code that is both efficient and readable.",
                "The ability to type without looking at the keyboard significantly boosts productivity.",
                "Touch typing involves memorizing the keyboard layout and developing muscle memory.",
                "Regular practice sessions, even short ones, can dramatically improve typing speed over time.",
                "Modern keyboards are designed with ergonomics in mind to reduce strain during long typing sessions."
            ],
            "高级": [
                "The development of typing skills parallels the evolution of written communication itself.",
                "Quantum computing represents a paradigm shift in how we process information at a fundamental level.",
                "Advancements in natural language processing have revolutionized human-computer interaction methodologies.",
                "The interdisciplinary nature of computer science necessitates proficiency in multiple technical domains.",
                "Optimizing algorithms for parallel processing requires a deep understanding of both hardware architecture and software design patterns."
            ],
            "中文练习": [
                "学习编程需要坚持不懈的练习和实践。",
                "打字速度是程序员工作效率的重要因素之一。",
                "熟能生巧，通过不断练习可以提高打字准确率。",
                "Python语言以其简洁优雅的语法而广受欢迎。",
                "人工智能正在改变我们生活和工作的方式。"
            ],
            "代码练习": [
                "def calculate_sum(numbers):\n    total = 0\n    for num in numbers:\n        total += num\n    return total",
                "function validateEmail(email) {\n    const regex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n    return regex.test(email);\n}",
                "SELECT users.name, orders.total \nFROM users \nINNER JOIN orders ON users.id = orders.user_id \nWHERE orders.date >= '2024-01-01';",
                "class Car:\n    def __init__(self, brand, model, year):\n        self.brand = brand\n        self.model = model\n        self.year = year",
                "try {\n    const response = await fetch('https://api.example.com/data');\n    const data = await response.json();\n    console.log(data);\n} catch (error) {\n    console.error('Error:', error);\n}"
            ]
        }

    def load_settings(self):
        """加载用户设置"""
        if os.path.exists("settings.json"):
            try:
                with open("settings.json", 'r') as f:
                    saved_settings = json.load(f)
                    self.settings.update(saved_settings)
            except:
                pass

    def save_settings(self):
        """保存用户设置"""
        with open("settings.json", 'w') as f:
            json.dump(self.settings, f, indent=2)

    def load_user_data(self):
        """加载用户数据"""
        if os.path.exists(self.data_file):
            try:
                with open(self.data_file, 'r') as f:
                    data = json.load(f)
                    self.favorites = data.get('favorites', [])
                    self.history = data.get('history', [])
            except:
                self.favorites = []
                self.history = []
        else:
            self.favorites = []
            self.history = []

        # 加载历史记录CSV
        if not os.path.exists(self.history_file):
            with open(self.history_file, 'w', newline='', encoding='utf-8') as f:
                writer = csv.writer(f)
                writer.writerow(
                    ['时间戳', '速度(WPM)', '准确率%', '用时(秒)', '文本长度', '难度'])

    def save_user_data(self):
        """保存用户数据"""
        data = {
            'favorites': self.favorites,
            'history': self.history[-100:]  # 只保存最近100条
        }
        with open(self.data_file, 'w', encoding='utf-8') as f:
            json.dump(data, f, ensure_ascii=False, indent=2)

        # 自动保存设置
        if self.settings.get('auto_save', True):
            self.save_settings()

    def setup_main_window(self):
        """设置主窗口界面"""
        # 菜单栏
        self.create_menu_bar()

        # 主题设置
        self.apply_theme()

        # 主框架
        main_container = ttk.Frame(self.main_window)
        main_container.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)

        # 顶部控制面板
        self.create_top_panel(main_container)

        # 中间文本区域
        self.create_text_area(main_container)

        # 底部控制面板
        self.create_bottom_panel(main_container)

        # 状态栏
        self.create_status_bar()

    def create_menu_bar(self):
        """创建菜单栏"""
        menubar = tk.Menu(self.main_window)
        self.main_window.config(menu=menubar)

        # 文件菜单
        file_menu = tk.Menu(menubar, tearoff=0)
        menubar.add_cascade(label="文件", menu=file_menu)
        file_menu.add_command(
            label="新建练习", command=self.load_random_text, accelerator="Ctrl+N")
        file_menu.add_command(label="打开文本文件...", command=self.open_text_file)
        file_menu.add_separator()
        file_menu.add_command(label="保存结果", command=self.save_results)
        file_menu.add_command(label="导出历史...", command=self.export_history)
        file_menu.add_separator()
        file_menu.add_command(
            label="退出", command=self.main_window.quit, accelerator="Ctrl+Q")

        # 编辑菜单
        edit_menu = tk.Menu(menubar, tearoff=0)
        menubar.add_cascade(label="编辑", menu=edit_menu)
        edit_menu.add_command(
            label="搜索文本...", command=self.open_search_window, accelerator="Ctrl+F")
        edit_menu.add_command(label="字体设置", command=self.open_font_settings)
        edit_menu.add_separator()
        edit_menu.add_command(
            label="添加到收藏夹", command=self.add_to_favorites, accelerator="Ctrl+D")
        edit_menu.add_command(label="管理收藏夹", command=self.manage_favorites)

        # 视图菜单
        view_menu = tk.Menu(menubar, tearoff=0)
        menubar.add_cascade(label="视图", menu=view_menu)
        view_menu.add_command(label="统计信息", command=self.open_stats_window)
        view_menu.add_command(label="练习历史", command=self.view_history)
        view_menu.add_checkbutton(label="显示计时器", variable=tk.BooleanVar(value=self.settings['show_timer']),
                                  command=self.toggle_timer)

        # 练习菜单
        practice_menu = tk.Menu(menubar, tearoff=0)
        menubar.add_cascade(label="练习", menu=practice_menu)
        practice_menu.add_command(
            label="开始练习", command=self.start_typing, accelerator="F2")
        practice_menu.add_command(
            label="暂停/继续", command=self.toggle_pause, accelerator="F3")
        practice_menu.add_command(
            label="结束练习", command=self.end_typing, accelerator="F4")
        practice_menu.add_separator()

        # 难度子菜单
        difficulty_menu = tk.Menu(practice_menu, tearoff=0)
        practice_menu.add_cascade(label="难度设置", menu=difficulty_menu)
        difficulties = ["入门级", "初级", "中级", "高级", "中文练习", "代码练习"]
        for diff in difficulties:
            difficulty_menu.add_command(label=diff,
                                        command=lambda d=diff: self.set_difficulty(d))

        # 工具菜单
        tools_menu = tk.Menu(menubar, tearoff=0)
        menubar.add_cascade(label="工具", menu=tools_menu)
        tools_menu.add_command(label="打字测试", command=self.speed_test)
        tools_menu.add_command(label="打字游戏", command=self.typing_game)
        tools_menu.add_command(label="自定义文本", command=self.custom_text)

        # 帮助菜单
        help_menu = tk.Menu(menubar, tearoff=0)
        menubar.add_cascade(label="帮助", menu=help_menu)
        help_menu.add_command(label="使用帮助", command=self.open_help_window)
        help_menu.add_command(label="键盘快捷键", command=self.show_shortcuts)
        help_menu.add_separator()
        help_menu.add_command(label="关于", command=self.show_about)
        help_menu.add_command(label="设置", command=self.open_settings_window)

        # 绑定快捷键
        self.main_window.bind('<Control-n>', lambda e: self.load_random_text())
        self.main_window.bind(
            '<Control-f>', lambda e: self.open_search_window())
        self.main_window.bind('<Control-q>', lambda e: self.main_window.quit())
        self.main_window.bind('<F2>', lambda e: self.start_typing())
        self.main_window.bind('<F3>', lambda e: self.toggle_pause())
        self.main_window.bind('<F4>', lambda e: self.end_typing())

    def create_top_panel(self, parent):
        """创建顶部控制面板"""
        top_frame = ttk.Frame(parent)
        top_frame.pack(fill=tk.X, pady=(0, 10))

        # 标题
        title_label = tk.Label(top_frame, text="极速打字王",
                               font=("微软雅黑", 20, "bold"), fg="#2c3e50")
        title_label.pack(side=tk.LEFT)

        # 控制按钮
        control_frame = ttk.Frame(top_frame)
        control_frame.pack(side=tk.RIGHT)

        button_config = {"width": 10, "padding": 5}

        ttk.Button(control_frame, text="开始(F2)", command=self.start_typing,
                   style="Accent.TButton", **button_config).pack(side=tk.LEFT, padx=2)

        ttk.Button(control_frame, text="暂停(F3)", command=self.toggle_pause,
                   **button_config).pack(side=tk.LEFT, padx=2)

        ttk.Button(control_frame, text="结束(F4)", command=self.end_typing,
                   **button_config).pack(side=tk.LEFT, padx=2)

        ttk.Button(control_frame, text="下一题", command=self.load_random_text,
                   **button_config).pack(side=tk.LEFT, padx=2)

        ttk.Button(control_frame, text="收藏", command=self.add_to_favorites,
                   **button_config).pack(side=tk.LEFT, padx=2)

        # 难度选择
        self.difficulty_var = tk.StringVar(
            value=self.settings.get('difficulty', 'medium'))
        diff_combo = ttk.Combobox(control_frame, textvariable=self.difficulty_var,
                                  values=list(self.text_library.keys()),
                                  state="readonly", width=12)
        diff_combo.pack(side=tk.LEFT, padx=2)
        diff_combo.bind('<<ComboboxSelected>>',
                        lambda e: self.load_difficulty_text())

    def create_text_area(self, parent):
        """创建文本显示区域"""
        # 原文显示区域
        text_container = ttk.Frame(parent)
        text_container.pack(fill=tk.BOTH, expand=True, pady=(0, 10))

        # 原文标签
        source_label = ttk.Label(
            text_container, text="练习文本:", font=("Arial", 11, "bold"))
        source_label.pack(anchor=tk.W, pady=(0, 5))

        # 原文文本框（带滚动条）
        source_frame = ttk.Frame(text_container)
        source_frame.pack(fill=tk.BOTH, expand=True)

        self.source_text = tk.Text(source_frame, wrap=tk.WORD,
                                   font=("Consolas",
                                         self.settings['font_size']),
                                   bg="#f8f9fa", relief=tk.FLAT, padx=10, pady=10)
        source_scrollbar = ttk.Scrollbar(
            source_frame, command=self.source_text.yview)
        self.source_text.config(yscrollcommand=source_scrollbar.set)

        self.source_text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        source_scrollbar.pack(side=tk.RIGHT, fill=tk.Y)

        # 输入区域标签
        input_label = ttk.Label(text_container, text="输入区域 (按任意键开始):",
                                font=("Arial", 11, "bold"))
        input_label.pack(anchor=tk.W, pady=(20, 5))

        # 输入文本框
        input_frame = ttk.Frame(text_container)
        input_frame.pack(fill=tk.BOTH, expand=True)

        self.input_text = tk.Text(input_frame, wrap=tk.WORD,
                                  font=("Consolas",
                                        self.settings['font_size']),
                                  relief=tk.SUNKEN, padx=10, pady=10)
        input_scrollbar = ttk.Scrollbar(
            input_frame, command=self.input_text.yview)
        self.input_text.config(yscrollcommand=input_scrollbar.set)

        self.input_text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        input_scrollbar.pack(side=tk.RIGHT, fill=tk.Y)

        # 绑定事件
        self.input_text.bind("<KeyPress>", self.on_key_press)
        self.input_text.bind("<KeyRelease>", self.on_key_release)

        # 配置标签样式
        self.source_text.tag_config("correct", foreground="#27ae60", font=(
            "Consolas", self.settings['font_size'], "bold"))
        self.source_text.tag_config("wrong", background="#fddede", foreground="#e74c3c",
                                    font=("Consolas", self.settings['font_size'], "bold"))
        self.source_text.tag_config("current", background="#3498db", foreground="white",
                                    font=("Consolas", self.settings['font_size'], "bold"))

    def create_bottom_panel(self, parent):
        """创建底部控制面板"""
        bottom_frame = ttk.Frame(parent)
        bottom_frame.pack(fill=tk.X, pady=(10, 0))

        # 统计信息
        stats_frame = ttk.LabelFrame(bottom_frame, text="实时统计", padding=10)
        stats_frame.pack(fill=tk.X)

        # 创建统计标签
        self.wpm_var = tk.StringVar(value="0")
        self.accuracy_var = tk.StringVar(value="0%")
        self.progress_var = tk.StringVar(value="0%")
        self.time_var = tk.StringVar(value="00:00")

        stats_grid = ttk.Frame(stats_frame)
        stats_grid.pack(expand=True)

        # 第一行：速度、准确率、进度
        ttk.Label(stats_grid, text="速度:", font=("Arial", 10)).grid(
            row=0, column=0, padx=10, sticky=tk.E)
        ttk.Label(stats_grid, textvariable=self.wpm_var, font=("Arial", 12, "bold"),
                  foreground="#3498db").grid(row=0, column=1, padx=(0, 20), sticky=tk.W)

        ttk.Label(stats_grid, text="准确率:", font=("Arial", 10)).grid(
            row=0, column=2, padx=10, sticky=tk.E)
        ttk.Label(stats_grid, textvariable=self.accuracy_var, font=("Arial", 12, "bold"),
                  foreground="#27ae60").grid(row=0, column=3, padx=(0, 20), sticky=tk.W)

        ttk.Label(stats_grid, text="进度:", font=("Arial", 10)).grid(
            row=0, column=4, padx=10, sticky=tk.E)
        ttk.Label(stats_grid, textvariable=self.progress_var, font=("Arial", 12, "bold"),
                  foreground="#9b59b6").grid(row=0, column=5, padx=(0, 20), sticky=tk.W)

        # 第二行：时间、错误数、评分
        self.errors_var = tk.StringVar(value="0")
        self.score_var = tk.StringVar(value="☆☆☆☆☆")

        ttk.Label(stats_grid, text="时间:", font=("Arial", 10)).grid(
            row=1, column=0, padx=10, pady=(10, 0), sticky=tk.E)
        ttk.Label(stats_grid, textvariable=self.time_var, font=("Arial", 12, "bold"),
                  foreground="#e67e22").grid(row=1, column=1, padx=(0, 20), pady=(10, 0), sticky=tk.W)

        ttk.Label(stats_grid, text="错误:", font=("Arial", 10)).grid(
            row=1, column=2, padx=10, pady=(10, 0), sticky=tk.E)
        ttk.Label(stats_grid, textvariable=self.errors_var, font=("Arial", 12, "bold"),
                  foreground="#e74c3c").grid(row=1, column=3, padx=(0, 20), pady=(10, 0), sticky=tk.W)

        ttk.Label(stats_grid, text="评分:", font=("Arial", 10)).grid(
            row=1, column=4, padx=10, pady=(10, 0), sticky=tk.E)
        ttk.Label(stats_grid, textvariable=self.score_var, font=("Arial", 12, "bold"),
                  foreground="#f1c40f").grid(row=1, column=5, padx=(0, 20), pady=(10, 0), sticky=tk.W)

    def create_status_bar(self):
        """创建状态栏"""
        self.status_bar = ttk.Frame(self.main_window, relief=tk.SUNKEN)
        self.status_bar.pack(side=tk.BOTTOM, fill=tk.X)

        self.status_label = ttk.Label(
            self.status_bar, text="就绪 | 按任意键开始练习", relief=tk.SUNKEN, anchor=tk.W)
        self.status_label.pack(side=tk.LEFT, fill=tk.X, expand=True)

        self.char_count_label = ttk.Label(
            self.status_bar, text="字数: 0", relief=tk.SUNKEN, anchor=tk.E, width=20)
        self.char_count_label.pack(side=tk.RIGHT)

        self.difficulty_label = ttk.Label(self.status_bar, text=f"难度: {self.difficulty_var.get()}",
                                          relief=tk.SUNKEN, anchor=tk.CENTER, width=20)
        self.difficulty_label.pack(side=tk.RIGHT)

    def apply_theme(self):
        """应用主题"""
        if self.settings['theme'] == 'dark':
            self.main_window.configure(bg='#2c3e50')
            style = ttk.Style()
            style.theme_use('clam')
            style.configure('TLabel', background='#2c3e50', foreground='white')
            style.configure('TFrame', background='#2c3e50')
            style.configure('TLabelframe', background='#2c3e50',
                            foreground='white')
            style.configure('TLabelframe.Label',
                            background='#2c3e50', foreground='white')
        else:
            style = ttk.Style()
            style.theme_use('clam')
            style.configure('Accent.TButton',
                            background='#3498db', foreground='white')

    def load_random_text(self):
        """加载随机文本"""
        difficulty = self.difficulty_var.get()
        if difficulty in self.text_library and self.text_library[difficulty]:
            self.load_specific_text(random.choice(
                self.text_library[difficulty]))
            self.difficulty_label.config(text=f"难度: {difficulty}")

    def load_difficulty_text(self):
        """加载指定难度的文本"""
        self.load_random_text()

    def load_specific_text(self, text):
        """加载特定文本"""
        self.current_text = text
        self.source_text.config(state=tk.NORMAL)
        self.source_text.delete(1.0, tk.END)
        self.source_text.insert(1.0, text)
        self.source_text.config(state=tk.DISABLED)

        self.input_text.delete(1.0, tk.END)
        self.reset_stats()
        self.input_text.focus()

        # 更新状态
        self.status_label.config(text="准备就绪 | 按任意键开始")
        self.char_count_label.config(text=f"字数: {len(text)}")

    def reset_stats(self):
        """重置统计信息"""
        self.start_time = None
        self.is_typing = False
        self.is_paused = False
        self.pause_time = 0

        # 重置显示
        self.wpm_var.set("0")
        self.accuracy_var.set("0%")
        self.progress_var.set("0%")
        self.time_var.set("00:00")
        self.errors_var.set("0")
        self.score_var.set("☆☆☆☆☆")

        # 停止计时器
        if self.timer_id:
            self.main_window.after_cancel(self.timer_id)
            self.timer_id = None

    def on_key_press(self, event):
        """按键按下事件"""
        if event.keysym in ('Shift_L', 'Shift_R', 'Control_L', 'Control_R',
                            'Alt_L', 'Alt_R', 'Caps_Lock'):
            return

        if not self.is_typing and not self.is_paused:
            self.start_typing()

    def start_typing(self):
        """开始打字"""
        if not self.is_typing:
            self.is_typing = True
            self.start_time = time.time()
            self.status_label.config(text="练习中...")
            self.update_timer()

    def on_key_release(self, event):
        """按键释放事件"""
        if not self.is_typing or self.is_paused:
            return

        user_input = self.input_text.get(1.0, tk.END).strip()

        # 实时高亮显示
        self.highlight_text(user_input)

        # 更新统计
        self.update_stats(user_input)

        # 检查是否完成
        if len(user_input) >= len(self.current_text):
            self.end_typing(force_end=True)

    def highlight_text(self, user_input):
        """高亮显示文本"""
        self.source_text.config(state=tk.NORMAL)
        self.source_text.delete(1.0, tk.END)

        for i, char in enumerate(self.current_text):
            tags = []
            if i < len(user_input):
                if user_input[i] == char:
                    tags.append("correct")
                else:
                    tags.append("wrong")
            if i == len(user_input):  # 当前位置
                tags.append("current")

            self.source_text.insert(tk.END, char, tuple(tags))

        self.source_text.config(state=tk.DISABLED)

        # 滚动到当前位置
        if len(user_input) < len(self.current_text):
            line_num = self.source_text.index(
                f"1.0+{len(user_input)}c").split('.')[0]
            self.source_text.see(f"{line_num}.0")

    def update_stats(self, user_input):
        """更新统计信息"""
        if not self.start_time:
            return

        # 计算耗时
        current_time = time.time()
        elapsed = current_time - self.start_time - self.pause_time

        # 更新时间显示
        minutes = int(elapsed) // 60
        seconds = int(elapsed) % 60
        self.time_var.set(f"{minutes:02d}:{seconds:02d}")

        # 计算进度
        progress = min(len(user_input) / len(self.current_text) * 100, 100)
        self.progress_var.set(f"{progress:.1f}%")

        # 计算准确率和错误数
        min_len = min(len(user_input), len(self.current_text))
        if min_len > 0:
            correct = 0
            errors = 0
            for i in range(min_len):
                if user_input[i] == self.current_text[i]:
                    correct += 1
                else:
                    errors += 1

            accuracy = (correct / min_len) * 100
            self.accuracy_var.set(f"{accuracy:.1f}%")
            self.errors_var.set(str(errors))

            # 更新总统计
            self.session_stats["total_chars"] = len(user_input)
            self.session_stats["correct_chars"] = correct
        else:
            accuracy = 0
            self.errors_var.set("0")

        # 计算速度
        if elapsed > 0:
            words = len(user_input) / 5
            wpm = (words / elapsed) * 60
            self.wpm_var.set(f"{wpm:.1f}")
        else:
            wpm = 0

        # 更新评分
        score = self.calculate_score(wpm, accuracy, progress)
        self.score_var.set(score)

    def calculate_score(self, wpm, accuracy, progress):
        """计算评分"""
        if progress < 10:
            return "☆☆☆☆☆"

        # 加权计算分数
        speed_score = min(wpm / 80, 1.0)  # 80 WPM为满分
        accuracy_score = accuracy / 100
        total_score = (speed_score * 0.3 + accuracy_score * 0.7) * 5

        # 转换为星星
        full_stars = int(total_score)
        half_star = 1 if total_score - full_stars >= 0.5 else 0

        stars = "★" * full_stars
        if half_star:
            stars += "½"
        stars += "☆" * (5 - full_stars - half_star)

        return stars

    def update_timer(self):
        """更新计时器"""
        if self.is_typing and not self.is_paused:
            if self.start_time:
                elapsed = int(time.time() - self.start_time - self.pause_time)
                minutes = elapsed // 60
                seconds = elapsed % 60
                self.time_var.set(f"{minutes:02d}:{seconds:02d}")

            self.timer_id = self.main_window.after(1000, self.update_timer)

    def toggle_pause(self):
        """切换暂停状态"""
        if not self.is_typing:
            messagebox.showinfo("提示", "请先开始练习")
            return

        if not self.is_paused:
            self.pause_typing()
        else:
            self.resume_typing()

    def pause_typing(self):
        """暂停打字"""
        if self.is_typing and not self.is_paused:
            self.is_paused = True
            self.pause_start = time.time()
            self.input_text.config(state=tk.DISABLED)
            self.status_label.config(text="已暂停 | 按F3继续")

            # 暂停计时器
            if self.timer_id:
                self.main_window.after_cancel(self.timer_id)
                self.timer_id = None

    def resume_typing(self):
        """继续打字"""
        if self.is_typing and self.is_paused:
            self.is_paused = False
            self.pause_time += time.time() - self.pause_start
            self.input_text.config(state=tk.NORMAL)
            self.input_text.focus()
            self.status_label.config(text="练习中...")
            self.update_timer()

    def end_typing(self, force_end=False):
        """结束打字"""
        if not self.is_typing and not force_end:
            return

        user_input = self.input_text.get(1.0, tk.END).strip()

        if not user_input and not force_end:
            response = messagebox.askyesno("确认", "您还没有输入任何内容，确定要结束吗？")
            if not response:
                return

        # 计算最终统计
        elapsed = time.time() - self.start_time - self.pause_time if self.start_time else 0

        min_len = min(len(user_input), len(self.current_text))
        if min_len > 0:
            correct = 0
            errors = 0
            for i in range(min_len):
                if user_input[i] == self.current_text[i]:
                    correct += 1
                else:
                    errors += 1

            accuracy = (correct / len(self.current_text)) * 100
        else:
            accuracy = 0
            errors = 0

        words = len(user_input) / 5
        wpm = (words / elapsed) * 60 if elapsed > 0 else 0

        # 保存记录
        record = {
            "timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
            "wpm": round(wpm, 1),
            "accuracy": round(accuracy, 1),
            "time": round(elapsed, 1),
            "length": len(self.current_text),
            "difficulty": self.difficulty_var.get(),
            "text": self.current_text[:50] + ("..." if len(self.current_text) > 50 else "")
        }

        self.history.append(record)

        # 保存到CSV
        with open(self.history_file, 'a', newline='', encoding='utf-8') as f:
            writer = csv.writer(f)
            writer.writerow([
                record["timestamp"],
                record["wpm"],
                record["accuracy"],
                record["time"],
                record["length"],
                record["difficulty"]
            ])

        # 更新会话统计
        self.session_stats["exercises_completed"] += 1
        self.session_stats["total_time"] += elapsed

        # 显示结果
        self.show_results_dialog(wpm, accuracy, elapsed, errors)

        # 重置状态
        self.reset_stats()
        self.status_label.config(text="练习完成 | 按任意键重新开始或选择下一题")

        # 自动保存
        if self.settings.get('auto_save', True):
            self.save_user_data()

    def show_results_dialog(self, wpm, accuracy, elapsed, errors):
        """显示结果对话框"""
        result_window = tk.Toplevel(self.main_window)
        result_window.title("练习结果")
        result_window.geometry("400x350")
        result_window.resizable(False, False)

        # 居中显示
        result_window.transient(self.main_window)
        result_window.grab_set()

        # 结果标题
        title_label = tk.Label(result_window, text="练习完成！",
                               font=("微软雅黑", 16, "bold"), fg="#2c3e50")
        title_label.pack(pady=20)

        # 结果详情
        details_frame = tk.Frame(result_window)
        details_frame.pack(pady=10, padx=20, fill=tk.X)

        # 使用网格布局
        metrics = [
            ("打字速度:", f"{wpm:.1f} WPM", "#3498db"),
            ("准确率:", f"{accuracy:.1f}%", accuracy >=
             90 and "#27ae60" or "#e74c3c"),
            ("所用时间:", f"{elapsed:.1f} 秒", "#e67e22"),
            ("错误数:", str(errors), "#e74c3c"),
            ("文本长度:", f"{len(self.current_text)} 字符", "#9b59b6")
        ]

        for i, (label, value, color) in enumerate(metrics):
            tk.Label(details_frame, text=label, font=("Arial", 11)).grid(
                row=i, column=0, sticky=tk.W, pady=5)
            tk.Label(details_frame, text=value, font=("Arial", 11, "bold"), fg=color).grid(
                row=i, column=1, sticky=tk.W, pady=5, padx=(10, 0))

        # 评价
        if accuracy >= 95 and wpm >= 50:
            evaluation = "🎉 太棒了！专业水平！"
        elif accuracy >= 90 and wpm >= 30:
            evaluation = "👍 做得很好！继续保持！"
        elif accuracy >= 80:
            evaluation = "👌 不错！准确率还可以再提高一点。"
        else:
            evaluation = "💪 继续努力，多练习会更好！"

        eval_label = tk.Label(result_window, text=evaluation, font=("Arial", 11),
                              wraplength=350, justify=tk.CENTER)
        eval_label.pack(pady=20)

        # 按钮
        button_frame = tk.Frame(result_window)
        button_frame.pack(pady=10)

        tk.Button(button_frame, text="下一题", command=lambda: [result_window.destroy(), self.load_random_text()],
                  bg="#3498db", fg="white", width=10, padx=10).pack(side=tk.LEFT, padx=5)
        tk.Button(button_frame, text="重新练习", command=lambda: [result_window.destroy(), self.load_specific_text(self.current_text)],
                  bg="#2ecc71", fg="white", width=10, padx=10).pack(side=tk.LEFT, padx=5)
        tk.Button(button_frame, text="关闭", command=result_window.destroy,
                  bg="#95a5a6", fg="white", width=10, padx=10).pack(side=tk.LEFT, padx=5)

    def add_to_favorites(self):
        """添加到收藏夹"""
        if self.current_text and self.current_text not in self.favorites:
            self.favorites.append(self.current_text)
            messagebox.showinfo("收藏", "已添加到收藏夹！")
            self.save_user_data()
        elif self.current_text in self.favorites:
            messagebox.showinfo("收藏", "已在收藏夹中！")

    def open_settings_window(self):
        """打开设置窗口"""
        if hasattr(self, 'settings_window') and self.settings_window and self.settings_window.winfo_exists():
            self.settings_window.lift()
            return

        self.settings_window = tk.Toplevel(self.main_window)
        self.settings_window.title("设置")
        self.settings_window.geometry("500x400")
        self.settings_window.resizable(False, False)
        self.settings_window.transient(self.main_window)

        # 设置标签页
        notebook = ttk.Notebook(self.settings_window)
        notebook.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)

        # 常规设置
        general_frame = ttk.Frame(notebook)
        notebook.add(general_frame, text="常规")

        ttk.Label(general_frame, text="字体大小:").grid(
            row=0, column=0, sticky=tk.W, pady=10, padx=10)
        font_size = tk.IntVar(value=self.settings['font_size'])
        font_spinbox = ttk.Spinbox(
            general_frame, from_=10, to=24, textvariable=font_size, width=10)
        font_spinbox.grid(row=0, column=1, sticky=tk.W, pady=10)

        ttk.Label(general_frame, text="主题:").grid(
            row=1, column=0, sticky=tk.W, pady=10, padx=10)
        theme_var = tk.StringVar(value=self.settings['theme'])
        ttk.Radiobutton(general_frame, text="浅色", variable=theme_var,
                        value="light").grid(row=1, column=1, sticky=tk.W)
        ttk.Radiobutton(general_frame, text="深色", variable=theme_var,
                        value="dark").grid(row=1, column=2, sticky=tk.W)

        ttk.Label(general_frame, text="默认难度:").grid(
            row=2, column=0, sticky=tk.W, pady=10, padx=10)
        default_difficulty = tk.StringVar(
            value=self.settings.get('difficulty', 'medium'))
        ttk.Combobox(general_frame, textvariable=default_difficulty,
                     values=list(self.text_library.keys()), state="readonly", width=15).grid(row=2, column=1, sticky=tk.W)

        # 练习设置
        practice_frame = ttk.Frame(notebook)
        notebook.add(practice_frame, text="练习")

        show_timer = tk.BooleanVar(value=self.settings.get('show_timer', True))
        ttk.Checkbutton(practice_frame, text="显示计时器", variable=show_timer).grid(
            row=0, column=0, sticky=tk.W, pady=10, padx=10)

        sound_effects = tk.BooleanVar(
            value=self.settings.get('sound_effects', True))
        ttk.Checkbutton(practice_frame, text="音效提示", variable=sound_effects).grid(
            row=1, column=0, sticky=tk.W, pady=10, padx=10)

        auto_save = tk.BooleanVar(value=self.settings.get('auto_save', True))
        ttk.Checkbutton(practice_frame, text="自动保存", variable=auto_save).grid(
            row=2, column=0, sticky=tk.W, pady=10, padx=10)

        # 保存按钮
        def save_settings():
            self.settings.update({
                'font_size': font_size.get(),
                'theme': theme_var.get(),
                'difficulty': default_difficulty.get(),
                'show_timer': show_timer.get(),
                'sound_effects': sound_effects.get(),
                'auto_save': auto_save.get()
            })
            self.save_settings()
            self.apply_theme()
            messagebox.showinfo("设置", "设置已保存，部分设置需要重启程序生效")
            self.settings_window.destroy()

        button_frame = ttk.Frame(self.settings_window)
        button_frame.pack(fill=tk.X, padx=10, pady=10)

        ttk.Button(button_frame, text="保存", command=save_settings,
                   width=10).pack(side=tk.RIGHT, padx=5)
        ttk.Button(button_frame, text="取消",
                   command=self.settings_window.destroy, width=10).pack(side=tk.RIGHT)

    def open_stats_window(self):
        """打开统计窗口"""
        if hasattr(self, 'stats_window') and self.stats_window and self.stats_window.winfo_exists():
            self.stats_window.lift()
            return

        self.stats_window = tk.Toplevel(self.main_window)
        self.stats_window.title("统计信息")
        self.stats_window.geometry("600x500")

        # 统计信息
        notebook = ttk.Notebook(self.stats_window)
        notebook.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)

        # 今日统计
        today_frame = ttk.Frame(notebook)
        notebook.add(today_frame, text="今日统计")

        # 历史统计
        history_frame = ttk.Frame(notebook)
        notebook.add(history_frame, text="历史记录")

        # 填充统计信息
        self.populate_stats(today_frame, history_frame)

    def open_search_window(self):
        """打开搜索窗口"""
        if hasattr(self, 'search_window') and self.search_window and self.search_window.winfo_exists():
            self.search_window.lift()
            return

        self.search_window = tk.Toplevel(self.main_window)
        self.search_window.title("搜索文本")
        self.search_window.geometry("700x500")

        # 搜索框
        search_frame = ttk.Frame(self.search_window)
        search_frame.pack(fill=tk.X, padx=10, pady=10)

        ttk.Label(search_frame, text="关键词:").pack(side=tk.LEFT, padx=(0, 5))
        search_var = tk.StringVar()
        search_entry = ttk.Entry(
            search_frame, textvariable=search_var, width=30)
        search_entry.pack(side=tk.LEFT, padx=(0, 5))

        ttk.Button(search_frame, text="搜索", command=lambda: self.perform_search(
            search_var.get())).pack(side=tk.LEFT)

        # 结果列表
        result_frame = ttk.Frame(self.search_window)
        result_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=(0, 10))

        self.search_results = tk.Listbox(result_frame, font=("Arial", 11))
        scrollbar = ttk.Scrollbar(
            result_frame, command=self.search_results.yview)
        self.search_results.config(yscrollcommand=scrollbar.set)

        self.search_results.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)

        # 加载所有文本
        self.all_texts = []
        for category, texts in self.text_library.items():
            for text in texts:
                self.all_texts.append((category, text))

        for category, text in self.all_texts:
            display_text = f"[{category}] {text[:80]}..." if len(
                text) > 80 else f"[{category}] {text}"
            self.search_results.insert(tk.END, display_text)

    def open_help_window(self):
        """打开帮助窗口"""
        if hasattr(self, 'help_window') and self.help_window and self.help_window.winfo_exists():
            self.help_window.lift()
            return

        self.help_window = tk.Toplevel(self.main_window)
        self.help_window.title("使用帮助")
        self.help_window.geometry("600x500")

        # 帮助内容
        help_text = """打字练习软件使用指南

基本操作：
1. 选择难度：在顶部选择适合您的难度级别
2. 开始练习：在输入框中按任意键开始计时
3. 暂停/继续：按F3或点击暂停按钮
4. 结束练习：按F4或点击结束按钮
5. 下一题：完成当前练习后点击下一题

快捷键：
F2 - 开始练习
F3 - 暂停/继续
F4 - 结束练习
Ctrl+N - 新建练习
Ctrl+F - 搜索文本
Ctrl+D - 添加到收藏夹
Ctrl+Q - 退出程序

评分标准：
★★★★★ - 优秀 (准确率>95%，速度>50WPM)
★★★★☆ - 良好 (准确率>90%，速度>40WPM)
★★★☆☆ - 一般 (准确率>85%，速度>30WPM)
★★☆☆☆ - 需改进 (准确率>80%，速度>20WPM)
★☆☆☆☆ - 继续努力

提示：
• 保持正确的坐姿和手指位置
• 开始时注重准确率，再逐步提高速度
• 每天坚持练习15-30分钟效果最佳
• 使用合适的键盘可以提升打字体验

如有问题，请联系技术支持。"""

        help_text_widget = scrolledtext.ScrolledText(
            self.help_window, wrap=tk.WORD, font=("Arial", 11))
        help_text_widget.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
        help_text_widget.insert(1.0, help_text)
        help_text_widget.config(state=tk.DISABLED)

    def show_about(self):
        """显示关于窗口"""
        about_window = tk.Toplevel(self.main_window)
        about_window.title("关于")
        about_window.geometry("400x300")
        about_window.resizable(False, False)

        about_text = """极速打字王 v2.0

一款功能强大的打字练习软件
帮助您提高打字速度和准确率

主要功能：
• 多难度级别练习
• 实时统计和评分
• 历史记录跟踪
• 收藏夹管理
• 多种文本类型
• 个性化设置

开发者：Python开发团队
版本：2.0.0
发布日期：2024年

感谢使用本软件！"""

        text_widget = tk.Text(about_window, wrap=tk.WORD,
                              font=("Arial", 11), height=15, width=40)
        text_widget.pack(fill=tk.BOTH, expand=True, padx=20, pady=20)
        text_widget.insert(1.0, about_text)
        text_widget.config(state=tk.DISABLED)

        ttk.Button(about_window, text="确定",
                   command=about_window.destroy).pack(pady=(0, 20))

    def toggle_timer(self):
        """切换计时器显示"""
        self.settings['show_timer'] = not self.settings.get('show_timer', True)
        self.save_settings()

    def set_difficulty(self, difficulty):
        """设置难度"""
        self.difficulty_var.set(difficulty)
        self.load_random_text()

    def perform_search(self, keyword):
        """执行搜索"""
        self.search_results.delete(0, tk.END)

        for category, text in self.all_texts:
            if not keyword or keyword.lower() in text.lower() or keyword.lower() in category.lower():
                display_text = f"[{category}] {text[:80]}..." if len(
                    text) > 80 else f"[{category}] {text}"
                self.search_results.insert(tk.END, display_text)

    def populate_stats(self, today_frame, history_frame):
        """填充统计信息"""
        # 今日统计
        today = datetime.now().strftime("%Y-%m-%d")
        today_records = [
            r for r in self.history if r['timestamp'].startswith(today)]

        if today_records:
            total_exercises = len(today_records)
            avg_wpm = sum(r['wpm'] for r in today_records) / total_exercises
            avg_accuracy = sum(r['accuracy']
                               for r in today_records) / total_exercises
            total_time = sum(r['time'] for r in today_records)

            stats_text = f"""今日练习统计：

练习次数：{total_exercises} 次
平均速度：{avg_wpm:.1f} WPM
平均准确率：{avg_accuracy:.1f}%
总用时：{total_time:.0f} 秒
总字符数：{sum(r['length'] for r in today_records)} 个

今日最佳：
最高速度：{max(r['wpm'] for r in today_records):.1f} WPM
最高准确率：{max(r['accuracy'] for r in today_records):.1f}%
"""
        else:
            stats_text = "今日暂无练习记录\n开始您的第一次练习吧！"

        today_label = tk.Label(today_frame, text=stats_text,
                               font=("Arial", 11), justify=tk.LEFT)
        today_label.pack(pady=20, padx=20, anchor=tk.W)

        # 历史记录
        if hasattr(self, 'history_table'):
            self.history_table.destroy()

        columns = ('时间', '速度(WPM)', '准确率%', '用时(秒)', '长度', '难度')
        self.history_table = ttk.Treeview(
            history_frame, columns=columns, show='headings', height=15)

        for col in columns:
            self.history_table.heading(col, text=col)
            self.history_table.column(col, width=80, anchor=tk.CENTER)

        # 添加滚动条
        scrollbar = ttk.Scrollbar(
            history_frame, orient=tk.VERTICAL, command=self.history_table.yview)
        self.history_table.configure(yscrollcommand=scrollbar.set)

        self.history_table.pack(
            side=tk.LEFT, fill=tk.BOTH, expand=True, padx=10, pady=10)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y, pady=10)

        # 添加数据
        for record in reversed(self.history[-50:]):  # 显示最近50条
            self.history_table.insert('', tk.END, values=(
                record['timestamp'][11:19],  # 只显示时间
                record['wpm'],
                f"{record['accuracy']:.1f}",
                f"{record['time']:.1f}",
                record['length'],
                record['difficulty']
            ))

    def manage_favorites(self):
        """管理收藏夹"""
        if not hasattr(self, 'favorites') or not self.favorites:
            messagebox.showinfo("收藏夹", "收藏夹为空")
            return

        fav_window = tk.Toplevel(self.main_window)
        fav_window.title("收藏夹管理")
        fav_window.geometry("600x400")

        # 收藏列表
        listbox = tk.Listbox(fav_window, font=(
            "Arial", 11), selectmode=tk.SINGLE)
        scrollbar = ttk.Scrollbar(fav_window, command=listbox.yview)
        listbox.config(yscrollcommand=scrollbar.set)

        for i, text in enumerate(self.favorites, 1):
            display_text = f"{i}. {text[:100]}..." if len(
                text) > 100 else f"{i}. {text}"
            listbox.insert(tk.END, display_text)

        listbox.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=10, pady=10)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y, pady=10)

        # 按钮
        button_frame = ttk.Frame(fav_window)
        button_frame.pack(fill=tk.X, padx=10, pady=(0, 10))

        def load_favorite():
            selection = listbox.curselection()
            if selection:
                self.load_specific_text(self.favorites[selection[0]])
                fav_window.destroy()

        def remove_favorite():
            selection = listbox.curselection()
            if selection:
                self.favorites.pop(selection[0])
                self.save_user_data()
                fav_window.destroy()
                self.manage_favorites()  # 刷新窗口

        ttk.Button(button_frame, text="练习", command=load_favorite).pack(
            side=tk.LEFT, padx=5)
        ttk.Button(button_frame, text="删除", command=remove_favorite).pack(
            side=tk.LEFT, padx=5)
        ttk.Button(button_frame, text="关闭", command=fav_window.destroy).pack(
            side=tk.RIGHT, padx=5)

    def open_text_file(self):
        """打开文本文件"""
        file_path = filedialog.askopenfilename(
            title="选择文本文件",
            filetypes=[("文本文件", "*.txt"), ("所有文件", "*.*")]
        )

        if file_path:
            try:
                with open(file_path, 'r', encoding='utf-8') as f:
                    content = f.read()
                    if content:
                        self.load_specific_text(content[:1000])  # 限制长度
            except Exception as e:
                messagebox.showerror("错误", f"无法读取文件: {str(e)}")

    def save_results(self):
        """保存结果"""
        if not self.history:
            messagebox.showinfo("提示", "没有可保存的结果")
            return

        file_path = filedialog.asksaveasfilename(
            title="保存结果",
            defaultextension=".csv",
            filetypes=[("CSV文件", "*.csv"), ("文本文件", "*.txt")]
        )

        if file_path:
            try:
                with open(file_path, 'w', newline='', encoding='utf-8') as f:
                    writer = csv.writer(f)
                    writer.writerow(['时间戳', '速度(WPM)', '准确率%',
                                    '用时(秒)', '文本长度', '难度', '文本片段'])
                    for record in self.history:
                        writer.writerow([
                            record['timestamp'],
                            record['wpm'],
                            record['accuracy'],
                            record['time'],
                            record['length'],
                            record['difficulty'],
                            record['text']
                        ])
                messagebox.showinfo("成功", "结果已保存")
            except Exception as e:
                messagebox.showerror("错误", f"保存失败: {str(e)}")

    def export_history(self):
        """导出历史记录"""
        self.save_results()

    def view_history(self):
        """查看历史记录"""
        self.open_stats_window()

    def speed_test(self):
        """打字测试"""
        test_window = tk.Toplevel(self.main_window)
        test_window.title("打字速度测试")
        test_window.geometry("500x400")

        # 测试说明
        instructions = """打字速度测试说明：

1. 测试时长：60秒
2. 测试文本：随机英文文章
3. 评分标准：
   - 40 WPM以下：初学者
   - 40-60 WPM：一般水平
   - 60-80 WPM：熟练水平
   - 80 WPM以上：专业水平

点击开始按钮开始测试。"""

        tk.Label(test_window, text=instructions, justify=tk.LEFT,
                 font=("Arial", 10), wraplength=450).pack(pady=20, padx=20)

        ttk.Button(test_window, text="开始测试",
                   command=lambda: self.start_speed_test(test_window)).pack(pady=10)

    def start_speed_test(self, parent_window):
        """开始速度测试"""
        parent_window.destroy()
        # 这里可以添加速度测试的具体实现
        messagebox.showinfo("提示", "速度测试功能开发中...")

    def typing_game(self):
        """打字游戏"""
        messagebox.showinfo("提示", "打字游戏功能开发中...")

    def custom_text(self):
        """自定义文本"""
        text_window = tk.Toplevel(self.main_window)
        text_window.title("自定义文本")
        text_window.geometry("600x400")

        tk.Label(text_window, text="请输入自定义练习文本:").pack(pady=10)

        text_widget = scrolledtext.ScrolledText(
            text_window, wrap=tk.WORD, height=15)
        text_widget.pack(fill=tk.BOTH, expand=True, padx=10, pady=(0, 10))

        def load_custom_text():
            text = text_widget.get(1.0, tk.END).strip()
            if text:
                self.load_specific_text(text)
                text_window.destroy()
            else:
                messagebox.showwarning("警告", "请输入文本内容")

        button_frame = ttk.Frame(text_window)
        button_frame.pack(fill=tk.X, padx=10, pady=(0, 10))

        ttk.Button(button_frame, text="使用此文本", command=load_custom_text).pack(
            side=tk.RIGHT, padx=5)
        ttk.Button(button_frame, text="取消",
                   command=text_window.destroy).pack(side=tk.RIGHT)

    def open_font_settings(self):
        """打开字体设置"""
        font_window = tk.Toplevel(self.main_window)
        font_window.title("字体设置")
        font_window.geometry("300x200")

        ttk.Label(font_window, text="字体大小:").pack(pady=10)

        font_size = tk.IntVar(value=self.settings['font_size'])
        spinbox = ttk.Spinbox(font_window, from_=10, to=24,
                              textvariable=font_size, width=10)
        spinbox.pack(pady=5)

        def apply_font():
            self.settings['font_size'] = font_size.get()
            self.source_text.config(
                font=("Consolas", self.settings['font_size']))
            self.input_text.config(
                font=("Consolas", self.settings['font_size']))
            messagebox.showinfo("提示", "字体大小已更新")
            font_window.destroy()

        ttk.Button(font_window, text="应用", command=apply_font).pack(pady=20)

    def show_shortcuts(self):
        """显示快捷键"""
        shortcuts = """键盘快捷键：

F2 - 开始练习
F3 - 暂停/继续
F4 - 结束练习
Ctrl+N - 新建练习
Ctrl+F - 搜索文本
Ctrl+D - 添加到收藏夹
Ctrl+Q - 退出程序

编辑快捷键：
Ctrl+A - 全选
Ctrl+C - 复制
Ctrl+V - 粘贴
Ctrl+Z - 撤销
Ctrl+Y - 重做"""

        shortcut_window = tk.Toplevel(self.main_window)
        shortcut_window.title("快捷键")
        shortcut_window.geometry("400x300")

        text_widget = tk.Text(
            shortcut_window, wrap=tk.WORD, font=("Consolas", 11))
        text_widget.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
        text_widget.insert(1.0, shortcuts)
        text_widget.config(state=tk.DISABLED)

        ttk.Button(shortcut_window, text="关闭",
                   command=shortcut_window.destroy).pack(pady=10)


# 运行程序
if __name__ == "__main__":
    app = TypingPracticeApp()
