feat: 添加学生成绩排行榜功能

- 新增 app.py 和 main.py 文件,实现学生成绩排行榜功能
- 添加 CSV 文件处理逻辑,支持成绩数据导入
- 实现成绩排行榜的图形化展示,包括搜索、重新加载等功能
- 新增成绩统计和可视化功能- 添加 .idea 相关配置文件,配置项目环境和样式
This commit is contained in:
sairate 2025-05-24 14:33:59 +08:00
commit 58d6e90c39
13 changed files with 271 additions and 0 deletions

3
.idea/.gitignore generated vendored Normal file
View File

@ -0,0 +1,3 @@
# 默认忽略的文件
/shelf/
/workspace.xml

10
.idea/autopai.iml generated Normal file
View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.venv" />
</content>
<orderEntry type="jdk" jdkName="Python 3.10 (autopai)" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

6
.idea/encodings.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="file://$PROJECT_DIR$/score.csv" charset="GBK" />
</component>
</project>

View File

@ -0,0 +1,14 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="PyPackageRequirementsInspection" enabled="true" level="WARNING" enabled_by_default="true">
<option name="ignoredPackages">
<value>
<list size="1">
<item index="0" class="java.lang.String" itemvalue="numpy" />
</list>
</value>
</option>
</inspection_tool>
</profile>
</component>

View File

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>

10
.idea/material_theme_project_new.xml generated Normal file
View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="MaterialThemeProjectNewConfig">
<option name="metadata">
<MTProjectMetadataState>
<option name="userId" value="-1a3ed073:19700c566e2:-7ffa" />
</MTProjectMetadataState>
</option>
</component>
</project>

7
.idea/misc.xml generated Normal file
View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Black">
<option name="sdkName" value="Python 3.10 (autopai)" />
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.10 (autopai)" project-jdk-type="Python SDK" />
</project>

8
.idea/modules.xml generated Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/autopai.iml" filepath="$PROJECT_DIR$/.idea/autopai.iml" />
</modules>
</component>
</project>

6
.idea/vcs.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

139
app.py Normal file
View File

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

42
main.py Normal file
View File

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

4
score.csv Normal file
View File

@ -0,0 +1,4 @@
姓名,成绩
张三,85
李四,90
王五,100
1 姓名 成绩
2 张三 85
3 李四 90
4 王五 100

16
students.csv Normal file
View File

@ -0,0 +1,16 @@
姓名,成绩
张三,85
李四,90
王五,100
赵六,72
孙七,59
周八,66
吴九,88
郑十,93
冯十一,45
陈十二,76
褚十三,99
卫十四,61
蒋十五,38
沈十六,82
韩十七,91
1 姓名 成绩
2 张三 85
3 李四 90
4 王五 100
5 赵六 72
6 孙七 59
7 周八 66
8 吴九 88
9 郑十 93
10 冯十一 45
11 陈十二 76
12 褚十三 99
13 卫十四 61
14 蒋十五 38
15 沈十六 82
16 韩十七 91