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.

422 lines
14 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.

"""
无人机决策系统 - 主界面模块
作者:刘宇杰
日期2025-07-13
功能说明:
本模块实现主界面,支持文件上传、分析、结果展示、历史记录等功能。
"""
import tkinter as tk
import json
from tkinter import ttk, filedialog, messagebox
from PIL import Image, ImageTk
from io import BytesIO
import base64
from gui.styles import apply_style
from core.analysis import AnalysisEngine
from utils.database import DatabaseManager
from gui.history_window import HistoryWindow
class MainWindow:
"""
主界面类,提供文件上传、分析、结果查看等功能。
"""
def __init__(self, user):
"""
初始化主窗口
:param user: 当前登录的用户信息
"""
self.user = user
self.analysis_engine = AnalysisEngine()
self.db_manager = DatabaseManager()
# 创建主窗口
self.root = tk.Tk()
self.root.title(f"无人机决策系统 - 欢迎, {user['username']}")
self.root.geometry("900x700")
apply_style(self.root)
# 当前显示的分析结果
self.current_result = None
# 创建UI元素
self._create_widgets()
# 运行主循环
self.root.mainloop()
def _create_widgets(self):
"""创建主窗口的所有UI元素"""
# 主框架
main_frame = ttk.Frame(self.root)
main_frame.pack(expand=True, fill=tk.BOTH, padx=10, pady=10)
# 左侧面板(文件上传)
left_panel = ttk.Frame(main_frame, width=300)
left_panel.pack(side=tk.LEFT, fill=tk.Y, padx=5, pady=5)
left_panel.pack_propagate(False)
# 右侧面板(结果显示)
right_panel = ttk.Frame(main_frame)
right_panel.pack(side=tk.RIGHT, expand=True, fill=tk.BOTH, padx=5, pady=5)
# 左侧面板内容
self._create_upload_section(left_panel)
self._create_history_section(left_panel)
# 右侧面板内容
self._create_result_section(right_panel)
def _create_upload_section(self, parent):
"""创建上传文件区域"""
section_frame = ttk.LabelFrame(parent, text="上传文件", padding=10)
section_frame.pack(fill=tk.X, pady=5)
# 文本上传
text_frame = ttk.Frame(section_frame)
text_frame.pack(fill=tk.X, pady=5)
ttk.Button(
text_frame,
text="上传文本文件",
command=self._upload_text_file
).pack(side=tk.LEFT, padx=5)
# 或
ttk.Label(text_frame, text="").pack(side=tk.LEFT, padx=5)
# 文本输入
self.text_input = tk.Text(
section_frame,
height=10,
wrap=tk.WORD,
font=("Helvetica", 10)
)
self.text_input.pack(fill=tk.X, pady=5)
# 图像上传
image_frame = ttk.Frame(section_frame)
image_frame.pack(fill=tk.X, pady=5)
ttk.Button(
image_frame,
text="上传图像",
command=self._upload_image
).pack(side=tk.LEFT, padx=5)
# 分析按钮
ttk.Button(
section_frame,
text="开始分析",
command=self._analyze_content,
style="Accent.TButton"
).pack(fill=tk.X, pady=10)
# 打击计划按钮
ttk.Button(
section_frame,
text="生成打击计划",
command=self._generate_strike_plan,
style="Accent.TButton"
).pack(fill=tk.X, pady=5)
def _create_history_section(self, parent):
"""创建历史记录区域"""
section_frame = ttk.LabelFrame(parent, text="最近记录", padding=10)
section_frame.pack(fill=tk.BOTH, expand=True, pady=5)
# 历史记录列表
self.history_listbox = tk.Listbox(
section_frame,
height=10,
selectmode=tk.SINGLE
)
self.history_listbox.pack(fill=tk.BOTH, expand=True)
# 加载历史记录
self._load_history()
# 查看详情按钮
ttk.Button(
section_frame,
text="查看详情",
command=self._show_history_detail
).pack(fill=tk.X, pady=5)
# 打开历史窗口按钮
ttk.Button(
section_frame,
text="查看全部历史",
command=self._open_history_window
).pack(fill=tk.X, pady=5)
def _create_result_section(self, parent):
"""创建结果显示区域"""
# 结果标签页
self.notebook = ttk.Notebook(parent)
self.notebook.pack(expand=True, fill=tk.BOTH)
# 原始结果标签
raw_frame = ttk.Frame(self.notebook)
self.raw_text = tk.Text(
raw_frame,
wrap=tk.WORD,
font=("Helvetica", 10)
)
self.raw_text.pack(expand=True, fill=tk.BOTH)
scrollbar = ttk.Scrollbar(raw_frame, command=self.raw_text.yview)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
self.raw_text.config(yscrollcommand=scrollbar.set)
self.notebook.add(raw_frame, text="原始结果")
# 格式化结果标签
formatted_frame = ttk.Frame(self.notebook)
self.formatted_text = tk.Text(
formatted_frame,
wrap=tk.WORD,
font=("Helvetica", 10)
)
self.formatted_text.pack(expand=True, fill=tk.BOTH)
scrollbar = ttk.Scrollbar(formatted_frame, command=self.formatted_text.yview)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
self.formatted_text.config(yscrollcommand=scrollbar.set)
self.notebook.add(formatted_frame, text="格式化结果")
# 图像预览标签(如果有图像)
self.image_frame = ttk.Frame(self.notebook)
self.image_label = ttk.Label(self.image_frame)
self.image_label.pack(expand=True)
self.notebook.add(self.image_frame, text="图像预览", state="hidden")
def _load_history(self):
"""加载用户的历史记录"""
self.history_listbox.delete(0, tk.END)
records = self.db_manager.get_user_records(self.user['id'])
for record in records:
display_text = f"{record['created_at'][:16]} - {record['record_type']}"
self.history_listbox.insert(tk.END, display_text)
def _upload_text_file(self):
"""上传文本文件"""
file_path = filedialog.askopenfilename(
title="选择文本文件",
filetypes=[("文本文件", "*.txt *.pdf *.docx")]
)
if file_path:
try:
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
self.text_input.delete(1.0, tk.END)
self.text_input.insert(tk.END, content)
except Exception as e:
messagebox.showerror("错误", f"读取文件失败: {str(e)}")
def _upload_image(self):
"""上传图像文件"""
file_path = filedialog.askopenfilename(
title="选择图像文件",
filetypes=[("图像文件", "*.png *.jpg *.jpeg *.gif")]
)
if file_path:
try:
with open(file_path, 'rb') as f:
self.image_data = f.read()
# 显示预览
img = Image.open(BytesIO(self.image_data))
img.thumbnail((300, 300))
photo = ImageTk.PhotoImage(img)
self.image_label.config(image=photo)
setattr(self.image_label, 'image', photo)
self.notebook.tab(self.image_frame, state="normal")
except Exception as e:
messagebox.showerror("错误", f"加载图像失败: {str(e)}")
def _analyze_content(self):
"""分析上传的内容"""
text_content = self.text_input.get("1.0", tk.END).strip()
image_data = getattr(self, 'image_data', None)
if not text_content and not image_data:
messagebox.showwarning("警告", "请上传文本或图像内容")
return
try:
if text_content:
# 分析文本
result = self.analysis_engine.analyze_text(
text_content,
"user_input.txt"
)
self.db_manager.add_analysis_record(
"text",
"user_input.txt",
result
)
elif image_data:
# 分析图像
result = self.analysis_engine.analyze_image(
image_data,
"uploaded_image.jpg"
)
self.db_manager.add_analysis_record(
"image",
"uploaded_image.jpg",
result
)
# 显示结果
self.current_result = result
self._display_results(result)
# 刷新历史记录
self._load_history()
messagebox.showinfo("成功", "分析完成")
except Exception as e:
messagebox.showerror("错误", f"分析失败: {str(e)}")
def _display_results(self, result):
"""显示分析结果"""
# 显示原始结果
self.raw_text.delete(1.0, tk.END)
self.raw_text.insert(tk.END, json.dumps(result, indent=2, ensure_ascii=False))
# 显示格式化结果
self.formatted_text.delete(1.0, tk.END)
ernie_analysis = result.get('ernie_analysis')
if isinstance(ernie_analysis, dict):
formatted = json.dumps(ernie_analysis, indent=2, ensure_ascii=False)
self.formatted_text.insert(tk.END, formatted)
else:
self.formatted_text.insert(tk.END, str(ernie_analysis))
# 如果有图像,显示图像预览
if result.get('type') == 'image' and 'processed_image' in result:
try:
img_data = base64.b64decode(result['processed_image'])
img = Image.open(BytesIO(img_data))
img.thumbnail((400, 400))
photo = ImageTk.PhotoImage(img)
self.image_label.config(image=photo)
setattr(self.image_label, 'image', photo)
self.notebook.tab(self.image_frame, state="normal")
except Exception as e:
print(f"显示图像失败: {str(e)}")
def _generate_strike_plan(self):
"""生成打击计划"""
if not self.current_result:
messagebox.showwarning("警告", "请先进行分析")
return
try:
# 在实际应用中,这里可能会使用多个分析结果
plan = self.analysis_engine.generate_strike_plan([self.current_result])
# 保存计划
self.db_manager.add_strike_plan(self.user['id'], plan)
# 显示计划
self._display_results(plan)
messagebox.showinfo("成功", "打击计划生成完成")
except Exception as e:
messagebox.showerror("错误", f"生成计划失败: {str(e)}")
def _show_history_detail(self):
"""显示选中的历史记录详情"""
selection = self.history_listbox.curselection()
if not selection:
messagebox.showwarning("警告", "请选择一条记录")
return
record_index = selection[0]
records = self.db_manager.get_user_records(self.user['id'])
if 0 <= record_index < len(records):
record = records[record_index]
try:
result = json.loads(record['analysis_result'])
self.current_result = result
self._display_results(result)
except json.JSONDecodeError:
messagebox.showerror("错误", "无法解析记录数据")
def _open_history_window(self):
"""打开历史记录窗口"""
HistoryWindow(self.user)
def unused_function_5():
s = 0
for i in range(10):
s += i
return s
class UnusedClassE:
def __init__(self):
self.name = 'E'
def get_name(self):
return self.name
unused_var_5 = 'main_window_unused'
unused_list_5 = list(range(3))
def unused_function_15():
return [i for i in range(40)]
def unused_function_16():
s = 1
for i in range(1, 10):
s *= i
return s
class UnusedClassO:
def __init__(self):
self.name = 'O'
def get_name(self):
return self.name
class UnusedClassP:
def __init__(self):
self.flag = False
def set_flag(self, val):
self.flag = val
def get_flag(self):
return self.flag
unused_var_20 = [str(i) for i in range(10)]
unused_var_21 = 123456
unused_var_22 = {'main': True}
def unused_function_27():
return [i for i in range(100)]
def unused_function_28():
s = 1
for i in range(1, 20):
s *= i
return s
class UnusedClassAA:
def __init__(self):
self.name = 'AA'
def get_name(self):
return self.name
class UnusedClassAB:
def __init__(self):
self.flag = False
def set_flag(self, val):
self.flag = val
def get_flag(self):
return self.flag
unused_var_39 = [str(i) for i in range(50)]
unused_var_40 = 654321
unused_var_41 = {'main2': False}