commit 58d6e90c39231fd018cc170c89412133e00e2e8e Author: sairate Date: Sat May 24 14:33:59 2025 +0800 feat: 添加学生成绩排行榜功能 - 新增 app.py 和 main.py 文件,实现学生成绩排行榜功能 - 添加 CSV 文件处理逻辑,支持成绩数据导入 - 实现成绩排行榜的图形化展示,包括搜索、重新加载等功能 - 新增成绩统计和可视化功能- 添加 .idea 相关配置文件,配置项目环境和样式 diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..359bb53 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# 默认忽略的文件 +/shelf/ +/workspace.xml diff --git a/.idea/autopai.iml b/.idea/autopai.iml new file mode 100644 index 0000000..8f9cc7e --- /dev/null +++ b/.idea/autopai.iml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..d76dfa0 --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..25bde2c --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,14 @@ + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/material_theme_project_new.xml b/.idea/material_theme_project_new.xml new file mode 100644 index 0000000..7a6cec0 --- /dev/null +++ b/.idea/material_theme_project_new.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..72c3367 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..50be764 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app.py b/app.py new file mode 100644 index 0000000..0e4aef5 --- /dev/null +++ b/app.py @@ -0,0 +1,139 @@ +import csv +import tkinter as tk +from tkinter import ttk, messagebox +from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg +import matplotlib.pyplot as plt + +def process_csv(filename): + try: + with open(filename, 'r', encoding='utf-8-sig') as csvfile: + reader = csv.DictReader(csvfile) + data = list(reader) + data = sorted(data, key=lambda x: int(x['成绩']), reverse=True) + return data + except FileNotFoundError: + messagebox.showerror("错误", f"文件未找到: {filename}") + return [] + except ValueError: + messagebox.showerror("错误", "成绩格式错误,请确保为整数") + return [] + except Exception as e: + messagebox.showerror("错误", f"处理CSV时出错:{e}") + return [] + +def show_chart(infos, parent): + import matplotlib + matplotlib.rcParams['font.sans-serif'] = ['SimHei'] # 支持中文 + matplotlib.rcParams['axes.unicode_minus'] = False + + names = [i['姓名'] for i in infos] + scores = [int(i['成绩']) for i in infos] + + fig, ax = plt.subplots(figsize=(6, 3)) + ax.bar(names, scores, color='#66b3ff') + ax.set_title('学生成绩柱状图') + ax.set_ylabel('成绩') + ax.set_xlabel('姓名') + plt.xticks(rotation=45) + + canvas = FigureCanvasTkAgg(fig, master=parent) + canvas.draw() + canvas.get_tk_widget().pack(pady=10) + + +def display_scores(infos): + window = tk.Tk() + window.title('学生成绩排行榜') + window.geometry('650x700') + window.configure(bg='#f0f4f7') + + # 标题 + tk.Label(window, text="学生成绩排行榜", bg='#f0f4f7', fg='#336699', + font=('Arial', 20, 'bold')).pack(pady=10) + + # 搜索框 + search_frame = tk.Frame(window, bg='#f0f4f7') + search_frame.pack() + + tk.Label(search_frame, text="搜索姓名:", bg='#f0f4f7').pack(side=tk.LEFT) + search_entry = tk.Entry(search_frame) + search_entry.pack(side=tk.LEFT) + + # 表格 + columns = ('姓名', '成绩') + tree = ttk.Treeview(window, columns=columns, show='headings', height=10) + tree.heading('姓名', text='姓名') + tree.heading('成绩', text='成绩') + tree.column('姓名', anchor='center', width=200) + tree.column('成绩', anchor='center', width=100) + + style = ttk.Style() + style.configure('Treeview', font=('Arial', 12), rowheight=28) + style.configure('Treeview.Heading', font=('Arial', 13, 'bold')) + + def populate_table(data): + for item in tree.get_children(): + tree.delete(item) + for info in data: + score = int(info['成绩']) + tag = 'normal' + if score >= 90: + tag = 'excellent' + elif score < 60: + tag = 'fail' + tree.insert('', tk.END, values=(info['姓名'], info['成绩']), tags=(tag,)) + + # 打标签上色 + tree.tag_configure('excellent', background='#d4edda') # 绿色 + tree.tag_configure('fail', background='#f8d7da') # 红色 + + populate_table(infos) + tree.pack(pady=10) + + # 成绩统计 + def show_stats(data): + if not data: + return + scores = [int(i['成绩']) for i in data] + avg = sum(scores) / len(scores) + highest = max(scores) + count = len(scores) + stats_label.config(text=f"平均分:{avg:.2f},最高分:{highest},总人数:{count}") + + stats_label = tk.Label(window, bg='#f0f4f7', font=('Arial', 12)) + stats_label.pack(pady=5) + show_stats(infos) + + # 搜索功能 + def search(): + name = search_entry.get().strip() + if not name: + populate_table(infos) + show_stats(infos) + return + filtered = [i for i in infos if name in i['姓名']] + populate_table(filtered) + show_stats(filtered) + + tk.Button(search_frame, text="搜索", command=search).pack(side=tk.LEFT, padx=5) + + # 重新加载按钮 + def reload(): + new_data = process_csv('score.csv') + if new_data: + nonlocal infos + infos = new_data + populate_table(infos) + show_stats(infos) + + tk.Button(window, text="重新加载成绩", command=reload).pack(pady=10) + + # 可视化柱状图 + show_chart(infos, window) + + window.mainloop() + +if __name__ == "__main__": + score_data = process_csv('students.csv') + if score_data: + display_scores(score_data) diff --git a/main.py b/main.py new file mode 100644 index 0000000..a4a4163 --- /dev/null +++ b/main.py @@ -0,0 +1,42 @@ +import csv +import tkinter as tk +from tkinter import ttk, messagebox +def process_csv(filename): + with open(filename, 'r') as csvfile: + contents = csv.DictReader(csvfile) + infos=list(contents) + infos=sorted(infos, key=lambda x:int(x['成绩']),reverse=True) + return infos + + +window = tk.Tk() +window.title('学生成绩排行榜') +window.geometry('500x400') +window.configure(bg='#f0f4f7') + +# 设置统一字体 +style = ttk.Style() +style.configure('Treeview', font=('华文行楷', 12), rowheight=28) +style.configure('Treeview.Heading', font=('华文行楷', 13, 'bold')) + +# 标题标签 +title_label = tk.Label(window, text="学生成绩排行榜", bg='#f0f4f7', fg='#336699',font=('华文行楷', 20, 'bold')) +title_label.pack(pady=15) + +# 表格 +columns = ('姓名', '成绩') +tree = ttk.Treeview(window, columns=columns, show='headings', height=12) + +tree.heading('姓名', text='姓名') +tree.heading('成绩', text='成绩') +tree.column('姓名', anchor='center', width=200) +tree.column('成绩', anchor='center', width=100) + +infos = process_csv('score.csv') +for info in infos: + tree.insert('', tk.END, values=(info['姓名'], info['成绩'])) + +tree.pack(pady=10) + +# 运行主窗口 +window.mainloop() diff --git a/score.csv b/score.csv new file mode 100644 index 0000000..df8fd48 --- /dev/null +++ b/score.csv @@ -0,0 +1,4 @@ +,ɼ +,85 +,90 +,100 \ No newline at end of file diff --git a/students.csv b/students.csv new file mode 100644 index 0000000..6cb9c09 --- /dev/null +++ b/students.csv @@ -0,0 +1,16 @@ +姓名,成绩 +张三,85 +李四,90 +王五,100 +赵六,72 +孙七,59 +周八,66 +吴九,88 +郑十,93 +冯十一,45 +陈十二,76 +褚十三,99 +卫十四,61 +蒋十五,38 +沈十六,82 +韩十七,91