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.
wh11/21412030436_王辉_计科2104_名言查询系...

216 lines
7.4 KiB

import tkinter as tk
from tkinter import messagebox, filedialog, simpledialog, ttk
import PIL
from PIL import Image, ImageTk
import string
import random
import difflib
import threading
# 从文本文件读取鲁迅名言
def load_quotes(filename):
with open(filename, 'r', encoding='utf-8') as file:
return [line.strip() for line in file if line.strip()]
# 文本预处理函数
def preprocess_text(text):
# 转小写并去除标点符号
return text.lower().translate(str.maketrans('', '', string.punctuation))
def calculate_similarity(input_text, quote):
input_processed = preprocess_text(input_text)
quote_processed = preprocess_text(quote)
return difflib.SequenceMatcher(None, input_processed, quote_processed).ratio()
# 预处理所有名言
def preprocess_all_quotes(quotes):
return [(quote, preprocess_text(quote)) for quote in quotes]
# 搜索名言的函数
def search_quote():
keyword = entry_keyword.get()
if not keyword:
messagebox.showwarning("警告", "请输入搜索关键词!")
return
results = []
progress_bar['value'] = 0
root.update_idletasks()
def search_task():
nonlocal results
keyword_processed = preprocess_text(keyword)
total_quotes = len(preprocessed_quotes)
for i, (quote, processed_quote) in enumerate(preprocessed_quotes):
similarity = difflib.SequenceMatcher(None, keyword_processed, processed_quote).ratio()
if similarity > 0.3 or keyword in quote: # 这里设置一个相似度阈值
highlighted_quote = highlight_keyword(quote, keyword)
results.append(f"相似度: {similarity:.2f}\n原文: {highlighted_quote}")
if (i + 1) % (total_quotes // 100) == 0: # 减少进度条更新频率
progress_bar['value'] = (i + 1) / total_quotes * 100
root.update_idletasks()
progress_bar['value'] = 100
root.update_idletasks()
if results:
show_paginated_results(results)
save_history(keyword, results)
else:
messagebox.showerror("错误", "我是鲁迅,我没有说过这句话!")
threading.Thread(target=search_task).start()
def highlight_keyword(text, keyword):
start = text.lower().find(keyword.lower())
if start != -1:
end = start + len(keyword)
return text[:start] + '[highlight]' + text[start:end] + '[/highlight]' + text[end:]
return text
def show_paginated_results(results):
result_window = tk.Toplevel(root)
result_window.title("查询结果")
result_text = tk.Text(result_window, wrap=tk.WORD, font=('Arial', 12))
result_text.pack(expand=True, fill=tk.BOTH)
for result in results:
result_text.insert(tk.END, result.replace('[highlight]', '').replace('[/highlight]', ''))
result_text.tag_config('highlight', background='yellow', foreground='black')
start_idx = '1.0'
while True:
start_idx = result_text.search('[highlight]', start_idx, stopindex=tk.END)
if not start_idx:
break
end_idx = result_text.search('[/highlight]', start_idx, stopindex=tk.END)
result_text.delete(start_idx, start_idx + '+10c')
result_text.delete(end_idx, end_idx + '+11c')
result_text.tag_add('highlight', start_idx, end_idx)
# 保存历史记录
def save_history(keyword, results):
with open("search_history.txt", "a", encoding='utf-8') as file:
file.write(f"搜索关键词: {keyword}\n")
file.write("\n".join(results) + "\n\n")
# 显示历史记录
def show_history():
history_window = tk.Toplevel(root)
history_window.title("搜索历史记录")
with open("search_history.txt", "r", encoding='utf-8') as file:
history_text = file.read()
history_display = tk.Text(history_window, wrap=tk.WORD, font=('Arial', 12))
history_display.pack(expand=True, fill=tk.BOTH)
history_display.insert(tk.END, history_text)
# 清空历史记录
def clear_history():
if messagebox.askyesno("清空历史记录", "确定要清空所有历史记录吗?"):
with open("search_history.txt", "w", encoding='utf-8') as file:
file.write("")
messagebox.showinfo("提示", "历史记录已清空")
# 导出搜索结果
def export_results():
filename = filedialog.asksaveasfilename(defaultextension=".txt", filetypes=[("Text files", "*.txt")])
if filename:
with open(filename, "w", encoding='utf-8') as file:
keyword = entry_keyword.get()
file.write(f"搜索关键词: {keyword}\n")
for quote, processed_quote in preprocessed_quotes:
similarity = difflib.SequenceMatcher(None, preprocess_text(keyword), processed_quote).ratio()
if similarity > 0.3 or keyword in quote:
file.write(f"相似度: {similarity:.2f}\n原文: {quote}\n")
# 获取随机名言
def get_random_quote():
random_quote = random.choice(quotes)
messagebox.showinfo("随机名言", random_quote)
# 显示关于信息
def show_about():
messagebox.showinfo("关于", "鲁迅名言查询\n版本: 1.0\n作者: Sky")
# 创建主窗口
root = tk.Tk()
root.title("鲁迅名言查询")
# 设置窗口大小
root.geometry("600x500")
# 创建菜单
menu_bar = tk.Menu(root)
root.config(menu=menu_bar)
file_menu = tk.Menu(menu_bar, tearoff=0)
file_menu.add_command(label="导出搜索结果", command=export_results)
file_menu.add_separator()
file_menu.add_command(label="退出", command=root.quit)
menu_bar.add_cascade(label="文件", menu=file_menu)
history_menu = tk.Menu(menu_bar, tearoff=0)
history_menu.add_command(label="查看历史记录", command=show_history)
history_menu.add_command(label="清空历史记录", command=clear_history)
menu_bar.add_cascade(label="历史记录", menu=history_menu)
help_menu = tk.Menu(menu_bar, tearoff=0)
help_menu.add_command(label="关于", command=show_about)
menu_bar.add_cascade(label="帮助", menu=help_menu)
# 加载图片并显示Logo
image_path = "image.png"
image = PIL.Image.open(image_path)
logo_image = PIL.ImageTk.PhotoImage(image)
logo_label = tk.Label(root, image=logo_image)
logo_label.pack(side=tk.LEFT, padx=10, pady=10)
# 从文件加载名言
quotes = load_quotes("book.txt")
preprocessed_quotes = preprocess_all_quotes(quotes) # 预处理所有名言
# 创建输入框和搜索按钮
input_frame = tk.Frame(root)
input_frame.pack(side=tk.RIGHT, padx=20, pady=20)
entry_keyword = tk.Entry(input_frame, font=('Arial', 14), width=30)
entry_keyword.pack(side=tk.TOP, pady=10)
btn_search = tk.Button(input_frame, text="搜索名言", font=('Arial', 14), command=search_quote)
btn_search.pack(side=tk.TOP)
btn_random = tk.Button(input_frame, text="随机名言", font=('Arial', 14), command=get_random_quote)
btn_random.pack(side=tk.TOP)
btn_history = tk.Button(input_frame, text="查看历史记录", font=('Arial', 14), command=show_history)
btn_history.pack(side=tk.TOP)
btn_export = tk.Button(input_frame, text="导出搜索结果", font=('Arial', 14), command=export_results)
btn_export.pack(side=tk.TOP)
progress_bar = ttk.Progressbar(root, orient='horizontal', mode='determinate', length=400)
progress_bar.pack(side=tk.BOTTOM, pady=10)
# 运行主循环
root.mainloop()