- 新增 app.py 和 main.py 文件,实现学生成绩排行榜功能 - 添加 CSV 文件处理逻辑,支持成绩数据导入 - 实现成绩排行榜的图形化展示,包括搜索、重新加载等功能 - 新增成绩统计和可视化功能- 添加 .idea 相关配置文件,配置项目环境和样式
140 lines
4.3 KiB
Python
140 lines
4.3 KiB
Python
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)
|