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.

260 lines
10 KiB

6 months ago
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()
6 months ago
self.wrong_attempts = 0 # 记录密码错误次数的计数器
6 months ago
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()
6 months ago
tk.Button(self, text="开始学习", command=self.login).pack(pady=10)
6 months ago
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:
6 months ago
self.wrong_attempts += 1 # 每次密码错误计数器加1
messagebox.showerror("错误", "用户名或密码错误!")
if self.wrong_attempts >= 3: # 检查错误次数是否达到限制
messagebox.showerror("警告", "密码错误次数过多,程序即将退出。")
self.quit() # 退出程序
6 months ago
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)
6 months ago
self.word_frame.pack(padx=20, pady=20)
6 months ago
self.next_button = tk.Button(self, text="下一个单词", command=self.show_next_word)
self.next_button.pack(side=tk.RIGHT, padx=5, pady=5)
6 months ago
6 months ago
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():
6 months ago
self.user_entry.config(fg="green") # 将输入框文字颜色设为绿色
6 months ago
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
# 达到错误次数限制时更新数据库
6 months ago
if self.word_error_count[self.current_word] > 2:
6 months ago
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("易错单词复习")
6 months ago
self.geometry("400x300")
6 months ago
# 数据库连接设置
6 months ago
self.db = pymysql.connect(
host="localhost", # MySQL服务器地址
user="root", # 数据库用户名
password="21412030117", # 数据库密码
database="word", # 数据库名
charset='utf8mb4', # 字符编码,根据需要调整
cursorclass=pymysql.cursors.DictCursor # 使用字典游标,方便通过列名访问数据
6 months ago
)
6 months ago
self.cursor = self.db.cursor()
6 months ago
self.text_widget = tk.Text(self, wrap=tk.WORD, width=40, height=10)
self.text_widget.pack(expand=True, fill=tk.BOTH, padx=10, pady=10)
6 months ago
# 获取易错单词
6 months ago
self.fetch_and_display_mistaken_words()
6 months ago
6 months ago
def fetch_and_display_mistaken_words(self):
self.cursor.execute("SELECT `word`, `meaning` FROM `words` WHERE `easily_mistaken` = 1")
mistaken_words = self.cursor.fetchall()
if mistaken_words:
self.display_words(mistaken_words)
6 months ago
else:
6 months ago
messagebox.showinfo("提示", "没有易错单词可供复习!")
self.destroy()
6 months ago
6 months ago
def display_words(self, words):
# 使用Text控件显示单词和意义
for idx, word_info in enumerate(words, start=1):
text_to_insert = f"{idx}. 单词: {word_info['word']}, 意义: {word_info['meaning']}\n"
self.text_widget.insert(tk.END, text_to_insert)
6 months ago
6 months ago
# 自动滚动到底部
self.text_widget.see(tk.END)
6 months ago
6 months ago
def on_closing(self):
self.db.close()
self.destroy()
6 months ago
def start_application():
root = tk.Tk()
root.withdraw() # 隐藏根窗口因为我们直接使用Toplevel作为登录界面
LoginPage(master=root) # 将主窗口作为master传给LoginPage便于后续操作
root.mainloop() # 主循环在此启动,控制整个应用的生命周期
if __name__ == "__main__":
start_application()