import tkinter as tk
from tkinter import ttk, messagebox
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import numpy as np

# 设置matplotlib支持中文显示
plt.rcParams["font.family"] = ["SimHei", "WenQuanYi Micro Hei", "Heiti TC"]
plt.rcParams["axes.unicode_minus"] = False  # 解决负号显示问题

class SimpleScoreChart:
    def __init__(self, root):
        self.root = root
        self.root.title("简易成绩走势图")
        self.root.geometry("800x600")
        self.root.resizable(True, True)
        
        # 预设多科目示例数据
        self.preset_data = {
            "数学": [85, 88, 92, 89, 95, 90],
            "语文": [82, 84, 80, 86, 88, 85],
            "英语": [78, 85, 89, 92, 90, 93],
            "物理": [90, 88, 85, 87, 92, 89]
        }
        self.current_subject = "数学"
        self.scores = self.preset_data[self.current_subject]
        self.exam_names = ["第1次", "第2次", "第3次", "第4次", "第5次", "第6次"]
        
        # 创建图表
        self.fig, self.ax = plt.subplots(figsize=(8, 4), dpi=100)
        self.fig.patch.set_facecolor('white')  # 设置图表背景为白色
        
        # 构建界面
        self.create_ui()
        # 初始绘制图表
        self.update_chart()

    def create_ui(self):
        """创建用户界面"""
        # ========== 顶部控制区域 ==========
        top_frame = tk.Frame(self.root, bg="#f0f0f0", padx=10, pady=10)
        top_frame.pack(fill="x")
        
        # 1. 科目选择
        ttk.Label(top_frame, text="选择科目：", font=("微软雅黑", 11)).grid(
            row=0, column=0, padx=5, pady=5, sticky="w")
        
        subject_var = tk.StringVar(value=self.current_subject)
        subject_combo = ttk.Combobox(
            top_frame, textvariable=subject_var, values=list(self.preset_data.keys()),
            font=("微软雅黑", 11), state="readonly", width=10
        )
        subject_combo.grid(row=0, column=1, padx=5, pady=5)
        subject_combo.bind("<<ComboboxSelected>>", self.on_subject_change)
        
        # 2. 自定义成绩输入
        ttk.Label(top_frame, text="自定义成绩（逗号分隔）：", font=("微软雅黑", 11)).grid(
            row=0, column=2, padx=5, pady=5, sticky="w")
        
        self.score_entry = ttk.Entry(top_frame, font=("微软雅黑", 11), width=30)
        self.score_entry.grid(row=0, column=3, padx=5, pady=5)
        # 填充当前科目成绩
        self.score_entry.insert(0, ",".join(map(str, self.scores)))
        
        # 3. 功能按钮
        update_btn = tk.Button(
            top_frame, text="更新图表", font=("微软雅黑", 11),
            bg="#4CAF50", fg="white", padx=10, command=self.on_update_click
        )
        update_btn.grid(row=0, column=4, padx=5, pady=5)
        
        save_btn = tk.Button(
            top_frame, text="保存图表", font=("微软雅黑", 11),
            bg="#2196F3", fg="white", padx=10, command=self.save_chart
        )
        save_btn.grid(row=0, column=5, padx=5, pady=5)
        
        # 4. 成绩统计展示
        stat_frame = tk.Frame(top_frame, bg="#e8f4fd", padx=10, pady=5)
        stat_frame.grid(row=0, column=6, padx=15, pady=5)
        
        self.mean_label = ttk.Label(stat_frame, text="平均分：--", font=("微软雅黑", 10))
        self.mean_label.pack(side="left", padx=5)
        
        self.max_label = ttk.Label(stat_frame, text="最高分：--", font=("微软雅黑", 10))
        self.max_label.pack(side="left", padx=5)
        
        self.min_label = ttk.Label(stat_frame, text="最低分：--", font=("微软雅黑", 10))
        self.min_label.pack(side="left", padx=5)
        
        # ========== 底部图表区域 ==========
        chart_frame = tk.Frame(self.root)
        chart_frame.pack(fill="both", expand=True, padx=10, pady=10)
        
        # 嵌入matplotlib画布
        self.canvas = FigureCanvasTkAgg(self.fig, chart_frame)
        self.canvas.get_tk_widget().pack(fill="both", expand=True)

    def calculate_stats(self):
        """计算成绩统计信息"""
        mean_score = round(np.mean(self.scores), 1)
        max_score = np.max(self.scores)
        min_score = np.min(self.scores)
        return mean_score, max_score, min_score

    def update_chart(self):
        """更新成绩图表"""
        # 清空原有图表
        self.ax.clear()
        
        # 计算统计信息
        mean_score, max_score, min_score = self.calculate_stats()
        
        # 更新统计标签
        self.mean_label.config(text=f"平均分：{mean_score}")
        self.max_label.config(text=f"最高分：{max_score}")
        self.min_label.config(text=f"最低分：{min_score}")
        
        # 绘制折线图
        x = range(len(self.scores))
        line = self.ax.plot(
            x, self.scores, 
            marker='o', markersize=9, linewidth=2.5,
            color='#2196F3', markerfacecolor='#4CAF50', markeredgecolor='white', markeredgewidth=2
        )
        
        # 添加数值标注
        for i, score in enumerate(self.scores):
            self.ax.text(
                i, score + 1.5, str(score), 
                ha='center', va='bottom', fontsize=9, fontweight='bold'
            )
        
        # 填充折线下方区域（渐变效果）
        self.ax.fill_between(
            x, self.scores, alpha=0.2, color='#2196F3'
        )
        
        # 设置图表样式
        self.ax.set_title(f"{self.current_subject}成绩趋势图", fontsize=16, pad=20, fontweight='bold')
        self.ax.set_xlabel("考试次数", fontsize=12)
        self.ax.set_ylabel("分数", fontsize=12)
        self.ax.set_xticks(x)
        self.ax.set_xticklabels(self.exam_names, fontsize=10)
        self.ax.set_ylim(0, 105)  # 分数范围0-105
        self.ax.grid(True, alpha=0.3, linestyle='--')
        
        # 设置坐标轴样式
        self.ax.spines['top'].set_visible(False)
        self.ax.spines['right'].set_visible(False)
        self.ax.spines['left'].set_color('#cccccc')
        self.ax.spines['bottom'].set_color('#cccccc')
        
        # 刷新画布
        self.canvas.draw()

    def on_subject_change(self, event):
        """切换科目"""
        self.current_subject = event.widget.get()
        self.scores = self.preset_data[self.current_subject]
        # 更新输入框内容
        self.score_entry.delete(0, tk.END)
        self.score_entry.insert(0, ",".join(map(str, self.scores)))
        # 重新绘制图表
        self.update_chart()

    def on_update_click(self):
        """点击更新图表按钮"""
        # 获取输入的成绩
        input_text = self.score_entry.get().strip()
        if not input_text:
            messagebox.showwarning("警告", "请输入成绩数据！")
            return
        
        # 解析成绩数据
        try:
            scores = [float(s.strip()) for s in input_text.split(",")]
            # 校验分数范围
            for score in scores:
                if score < 0 or score > 100:
                    messagebox.showwarning("警告", "分数必须在0-100之间！")
                    return
            self.scores = scores
            # 更新考试标签
            self.exam_names = [f"第{i+1}次" for i in range(len(scores))]
            # 重新绘制图表
            self.update_chart()
            messagebox.showinfo("成功", "图表已更新！")
        except ValueError:
            messagebox.showerror("错误", "请输入有效的数字，用逗号分隔！")

    def save_chart(self):
        """保存图表"""
        try:
            filename = f"{self.current_subject}_成绩走势图.png"
            self.fig.savefig(
                filename, dpi=300, bbox_inches='tight', 
                facecolor='white', edgecolor='none'
            )
            messagebox.showinfo("成功", f"图表已保存为：{filename}")
        except Exception as e:
            messagebox.showerror("错误", f"保存失败：{str(e)}")

if __name__ == "__main__":
    root = tk.Tk()
    app = SimpleScoreChart(root)
    root.mainloop()