You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

312 lines
12 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import tkinter as tk
from tkinter import messagebox
import random
import pymysql
class LoginPage(tk.Toplevel):
def __init__(self, master=None):
super().__init__(master)
self.title("登录")
self.geometry("200x200")
self.username_var = tk.StringVar()
self.password_var = tk.StringVar()
tk.Label(self, text="用户名:").pack()
tk.Entry(self, textvariable=self.username_var).pack()
tk.Label(self, text="密码:").pack()
tk.Entry(self, show="*", textvariable=self.password_var).pack()
tk.Button(self, text="登录", command=self.login).pack(pady=10)
def login(self):
username = self.username_var.get()
password = self.password_var.get()
if username == "a" and password == "123456":
self.master.destroy() # 关闭主窗口(如果有),这里假设直接关闭自身也行,取决于实际结构
MainApp().mainloop() # 登录成功后实例化MainApp并启动其主循环
else:
messagebox.showerror("错误", "用户名或密码错误!") # 登录失败,保持登录界面打开供用户重试
class MainApp(tk.Tk):
def __init__(self):
super().__init__()
self.title("单词学习")
self.geometry("200x200")
# 创建三个按钮
tk.Button(self, text="学习新单词", command=self.open_window1).pack(fill=tk.X, padx=10, pady=5)
tk.Button(self, text="复习单词", command=self.open_window2).pack(fill=tk.X, padx=10, pady=5)
tk.Button(self, text="易错单词查看", command=self.open_window3).pack(fill=tk.X, padx=10, pady=5)
def open_window1(self):
Window1(self)
def open_window2(self):
Window2(self)
def open_window3(self):
Window3(self)
class Window1(tk.Toplevel):
def __init__(self, master):
super().__init__(master)
self.title("单词学习界面")
# 初始化MySQL数据库连接
self.conn = pymysql.connect(
host="localhost", # MySQL服务器地址
user="root", # 数据库用户名
password="21412030117", # 数据库密码
database="word", # 数据库名
charset='utf8mb4', # 字符编码,根据需要调整
cursorclass=pymysql.cursors.DictCursor # 使用字典游标,方便通过列名访问数据
)
self.cursor = self.conn.cursor()
self.word_frame = tk.Frame(self)
self.word_frame.pack(padx=10, pady=10)
self.next_button = tk.Button(self, text="下一个单词", command=self.show_next_word)
self.next_button.pack(side=tk.RIGHT, padx=5, pady=5)
self.prev_button = tk.Button(self, text="上一个单词") # 实现逻辑待补充
self.prev_button.pack(side=tk.LEFT, padx=5, pady=5)
self.show_next_word() # 初始显示一个单词
def show_next_word(self):
# 查询并获取一个未学习的单词
query = ("SELECT word, meaning FROM words WHERE learned = 0 ORDER BY RAND() LIMIT 1")
self.cursor.execute(query)
word_row = self.cursor.fetchone()
if word_row:
word, meaning = word_row['word'], word_row['meaning'] # 使用字典访问列
self.display_word(word, meaning)
# 标记该单词为已学习
self.mark_word_as_learned(word)
else:
messagebox.showinfo("提示", "所有单词都已学习过!")
def display_word(self, word, meaning):
"""显示单词及其意义"""
for widget in self.word_frame.winfo_children():
widget.destroy()
tk.Label(self.word_frame, text=f"单词: {word}").pack(anchor=tk.W)
tk.Label(self.word_frame, text=f"意义: {meaning}").pack(anchor=tk.W)
def mark_word_as_learned(self, word):
"""将单词标记为已学习"""
update_query = ("UPDATE words SET learned = 1 WHERE word = %s")
self.cursor.execute(update_query, (word,))
self.conn.commit()
class Window2(tk.Toplevel):
def __init__(self, master):
super().__init__(master)
self.title("单词拼写测试")
self.conn = pymysql.connect(
host="localhost",
user="root",
password="21412030117",
database="word",
charset='utf8mb4',
cursorclass=pymysql.cursors.DictCursor
)
self.cursor = self.conn.cursor()
self.setup_ui()
self.protocol("WM_DELETE_WINDOW", self.on_closing)
self.word_error_count = {} # 新增:存储单词错误次数的字典
def setup_ui(self):
self.word_label = tk.Label(self, text="", font=("Arial", 16))
self.word_label.pack(pady=10)
self.entry_var = tk.StringVar()
self.user_entry = tk.Entry(self, textvariable=self.entry_var, font=("Arial", 14))
self.user_entry.pack(ipady=5, pady=10)
self.result_label = tk.Label(self, text="", fg="black", font=("Arial", 12))
self.result_label.pack(pady=5)
self.next_button = tk.Button(self, text="下一个单词", state=tk.DISABLED, command=self.show_next_word)
self.next_button.pack(pady=10)
self.show_next_word() # 初始化显示一个单词
def show_next_word(self):
self.next_button.config(state=tk.DISABLED) # 禁用按钮防止重复点击
self.cursor.execute("SELECT `word`, `meaning` FROM `words` WHERE `learned` = 1 ORDER BY RAND() LIMIT 1")
word_row = self.cursor.fetchone()
if word_row:
self.current_word = word_row['word']
self.current_meaning = word_row['meaning']
self.word_label.config(text=f"含义:{self.current_meaning}")
self.entry_var.set("") # 清空输入框
self.result_label.config(text="")
self.user_entry.bind("<Return>", lambda event: self.check_spelling()) # 绑定回车键检查拼写
else:
messagebox.showinfo("提示", "没有更多已学习的单词可供测试!")
self.destroy()
def check_spelling(self):
user_input = self.entry_var.get().strip().lower()
if user_input == self.current_word.lower():
self.user_entry.config(fg="green") # 将输入框文字颜色设为绿色
self.result_label.config(text="正确!", fg="green")
self.next_button.config(state=tk.NORMAL) # 正确后启用按钮
self.word_error_count[self.current_word] = 0 # 重置错误计数
else:
self.result_label.config(text=f"错误!", fg="red")
self.user_entry.delete(0, tk.END) # 清空输入框并显示正确答案
self.user_entry.insert(0, self.current_word) # 在输入框中显示正确答案
self.user_entry.config(fg="red") # 将输入框文字颜色设为红色
self.user_entry.unbind("<Return>") # 避免在显示答案时响应回车键
self.user_entry.bind("<Button-1>", lambda event: self.clear_and_rebind(event)) # 绑定左键点击事件以清除并重新绑定
# 更新错误计数
if self.current_word in self.word_error_count:
self.word_error_count[self.current_word] += 1
else:
self.word_error_count[self.current_word] = 1
# 达到错误次数限制时更新数据库
if self.word_error_count[self.current_word] > 3:
self.update_easily_mistaken_in_db()
def update_easily_mistaken_in_db(self):
"""更新数据库中单词的easily_mistaken字段为1"""
try:
update_query = (
"UPDATE `words` SET `easily_mistaken` = 1 "
"WHERE `word` = %s AND `easily_mistaken` != 1"
)
self.cursor.execute(update_query, (self.current_word,))
self.conn.commit()
print(f"单词'{self.current_word}'标记为易错单词。")
except Exception as e:
print(f"更新数据库时出错:{e}")
def clear_and_rebind(self, event):
self.user_entry.delete(0, tk.END) # 清空输入框
self.user_entry.config(fg="black") # 重置输入框文字颜色为黑色
self.user_entry.bind("<Return>", lambda event: self.check_spelling()) # 重新绑定回车键事件
def on_closing(self):
self.conn.close()
self.destroy()
class Window3(tk.Toplevel):
def __init__(self, master):
super().__init__(master)
self.title("易错单词复习")
self.geometry("400x300")
# 初始化数据库连接
self.db = pymysql.connect(
host="localhost", # MySQL服务器地址
user="root", # 数据库用户名
password="21412030117", # 数据库密码
database="word", # 数据库名
charset='utf8mb4', # 字符编码,根据需要调整
cursorclass=pymysql.cursors.DictCursor # 使用字典游标,方便通过列名访问数据
)
self.cursor = self.db.cursor()
# 获取易错单词
self.fetch_mistaken_words()
# UI设置
self.word_label = tk.Label(self, text="", font=("Arial", 14))
self.word_label.pack(pady=20)
# 按钮
button_frame = tk.Frame(self)
button_frame.pack(pady=10)
tk.Button(button_frame, text="上一个单词", command=self.show_previous_word, state=tk.DISABLED).pack(
side=tk.LEFT, padx=10)
tk.Button(button_frame, text="下一个单词", command=self.show_next_word).pack(side=tk.RIGHT, padx=10)
# 初始化显示第一个单词
self.show_current_word()
def fetch_mistaken_words(self):
self.cursor.execute("SELECT `word`, `meaning` FROM `words` WHERE `easily_mistaken` = 1 ORDER BY `id`")
self.mistaken_words = self.cursor.fetchall()
self.current_index = 0
self.total_words = len(self.mistaken_words)
if self.total_words == 0:
messagebox.showinfo("提示", "没有易错单词可供复习!")
self.destroy()
def show_current_word(self):
if self.total_words > 0:
word_info = self.mistaken_words[self.current_index]
self.word_label.config(text=f"单词: {word_info['word']}, 意义: {word_info['meaning']}")
# 更新按钮状态
self.update_button_states()
def show_next_word(self):
if self.current_index < self.total_words - 1:
self.current_index += 1
else:
self.current_index = 0
self.show_current_word()
def show_previous_word(self):
if self.current_index > 0:
self.current_index -= 1
else:
self.current_index = self.total_words - 1
self.show_current_word()
def update_button_states(self):
if self.current_index == 0:
self.button_previous.configure(state=tk.DISABLED)
else:
self.button_previous.configure(state=tk.NORMAL)
if self.current_index == self.total_words - 1:
self.button_next.configure(state=tk.DISABLED)
else:
self.button_next.configure(state=tk.NORMAL)
def on_closing(self):
# 关闭窗口前的清理工作,如关闭数据库连接
self.db.close()
super().destroy()
# 实例化Window3的正确位置
if __name__ == "__main__":
root = tk.Tk()
root.withdraw() # 如果需要隐藏主窗口
window3 = Window3(root)
window3.protocol("WM_DELETE_WINDOW", window3.on_closing)
window3.mainloop()
def main():
# 初始化Tkinter的根窗口
root = tk.Tk()
root.withdraw() # 可选:隐藏根窗口,如果你不打算显示它的话
# 创建并显示Window3实例
window3 = Window3(root)
window3.protocol("WM_DELETE_WINDOW", window3.on_closing)
window3.mainloop() # 开始Window3窗口的事件循环
def start_application():
root = tk.Tk()
root.withdraw() # 隐藏根窗口因为我们直接使用Toplevel作为登录界面
LoginPage(master=root) # 将主窗口作为master传给LoginPage便于后续操作
root.mainloop() # 主循环在此启动,控制整个应用的生命周期
if __name__ == "__main__":
start_application()