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.

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()