Python GUI 成绩管理系统 - 数据可视化
import tkinter as tk from tkinter import filedialog, messagebox import pandas as pd import matplotlib.pyplot as plt from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
class GradeManagementSystem: def init(self, master): self.master = master self.master.title('成绩管理系统') self.master.geometry('800x600')
self.data = pd.DataFrame(columns=['班级', '姓名', '学号', '语文', '数学', '英语', '总分', '平均分'])
self.current_class = None
tk.Label(self.master, text='成绩管理系统', font=('Arial', 16)).pack(pady=10)
tk.Button(self.master, text='加载数据', command=self.load_data).pack(pady=10)
tk.Button(self.master, text='录入成绩', command=self.add_grade).pack(pady=10)
tk.Button(self.master, text='查询成绩', command=self.search_grade).pack(pady=10)
tk.Button(self.master, text='排序成绩', command=self.sort_grade).pack(pady=10)
tk.Button(self.master, text='查找学生', command=self.find_student).pack(pady=10)
tk.Button(self.master, text='导出数据', command=self.export_data).pack(pady=10)
tk.Button(self.master, text='生成图表', command=self.plot_scores).pack(pady=10)
self.grade_table = tk.Frame(self.master)
self.grade_table.pack(pady=20)
self.grade_table()
def load_data(self):
file_path = filedialog.askopenfilename(title='选择文件')
if file_path.endswith('.xlsx') or file_path.endswith('.xls'):
self.data = pd.read_excel(file_path)
tk.messagebox.showinfo(title='提示', message='数据加载成功')
self.current_class = None
self.grade_table()
else:
tk.messagebox.showerror(title='错误', message='请选择Excel文件')
def add_grade(self):
add_window = tk.Toplevel(self.master)
add_window.title('录入成绩')
add_window.geometry('300x250')
tk.Label(add_window, text='请选择班级:').pack(pady=10)
class_var = tk.StringVar(add_window)
class_var.set(self.current_class)
class_menu = tk.OptionMenu(add_window, class_var, *self.data['班级'].unique())
class_menu.pack()
tk.Label(add_window, text='请输入姓名:').pack(pady=10)
name_entry = tk.Entry(add_window)
name_entry.pack()
tk.Label(add_window, text='请输入学号:').pack(pady=10)
id_entry = tk.Entry(add_window)
id_entry.pack()
tk.Label(add_window, text='请输入语文成绩:').pack(pady=10)
chinese_entry = tk.Entry(add_window)
chinese_entry.pack()
tk.Label(add_window, text='请输入数学成绩:').pack(pady=10)
math_entry = tk.Entry(add_window)
math_entry.pack()
tk.Label(add_window, text='请输入英语成绩:').pack(pady=10)
english_entry = tk.Entry(add_window)
english_entry.pack()
def add():
class_name = class_var.get()
name = name_entry.get()
student_id = id_entry.get()
chinese = chinese_entry.get()
math = math_entry.get()
english = english_entry.get()
if class_name and name and student_id and chinese and math and english:
try:
chinese = float(chinese)
math = float(math)
english = float(english)
total = chinese + math + english
average = total / 3
new_data = pd.DataFrame([[class_name, name, student_id, chinese, math, english, total, average]],
columns=['班级', '姓名', '学号', '语文', '数学', '英语', '总分', '平均分'])
self.data = pd.concat([self.data, new_data], ignore_index=True)
tk.messagebox.showinfo(title='提示', message='成绩录入成功')
self.grade_table()
except ValueError:
tk.messagebox.showerror(title='错误', message='成绩必须为数字')
else:
tk.messagebox.showerror(title='错误', message='所有字段均为必填项')
tk.Button(add_window, text='录入', command=add).pack(pady=10)
def search_grade(self):
search_window = tk.Toplevel(self.master)
search_window.title('查询成绩')
search_window.geometry('300x200')
tk.Label(search_window, text='请输入学号或姓名:').pack(pady=10)
search_entry = tk.Entry(search_window)
search_entry.pack()
def search():
keyword = search_entry.get()
if keyword:
result = self.data.loc[(self.data['姓名'] == keyword) | (self.data['学号'] == keyword)]
if len(result) > 0:
tk.messagebox.showinfo(title='查询结果', message=result.to_string(index=False))
else:
tk.messagebox.showerror(title='错误', message='未找到学生信息')
else:
tk.messagebox.showerror(title='错误', message='请输入关键词')
tk.Button(search_window, text='查询', command=search).pack(pady=10)
def sort_grade(self):
sort_window = tk.Toplevel(self.master)
sort_window.title('排序成绩')
sort_window.geometry('300x200')
tk.Label(sort_window, text='请选择排序方式:').pack(pady=10)
sort_var = tk.StringVar(sort_window, '总分')
tk.Radiobutton(sort_window, text='总分', variable=sort_var, value='总分').pack()
tk.Radiobutton(sort_window, text='平均分', variable=sort_var, value='平均分').pack()
tk.Label(sort_window, text='请选择班级(可选):').pack(pady=10)
class_var = tk.StringVar(sort_window)
class_menu = tk.OptionMenu(sort_window, class_var, *['所有班级']+list(self.data['班级'].unique()))
class_menu.pack()
def sort():
sort_col = sort_var.get()
class_name = class_var.get()
if sort_col:
if class_name != '所有班级':
self.current_class = class_name
self.grade_table()
data = self.data.loc[self.data['班级'] == class_name]
else:
self.current_class = None
self.grade_table()
data = self.data
data.sort_values(by=sort_col, ascending=False, inplace=True)
tk.messagebox.showinfo(title='提示', message='排序成功')
self.grade_table()
else:
tk.messagebox.showerror(title='错误', message='请选择排序方式')
tk.Button(sort_window, text='排序', command=sort).pack(pady=10)
def find_student(self):
find_window = tk.Toplevel(self.master)
find_window.title('查找学生')
find_window.geometry('300x200')
tk.Label(find_window, text='请输入学号:').pack(pady=10)
find_entry = tk.Entry(find_window)
find_entry.pack()
def find():
student_id = find_entry.get()
if student_id:
result = self.data.loc[self.data['学号'] == student_id]
if len(result) > 0:
tk.messagebox.showinfo(title='查询结果', message=result.to_string(index=False))
else:
tk.messagebox.showerror(title='错误', message='未找到学生信息')
else:
tk.messagebox.showerror(title='错误', message='请输入学号')
tk.Button(find_window, text='查找', command=find).pack(pady=10)
def export_data(self):
file_path = filedialog.asksaveasfilename(title='保存文件', defaultextension='.xlsx')
if file_path:
self.data.to_excel(file_path, index=False)
tk.messagebox.showinfo(title='提示', message='导出成功')
def plot_scores(self):
plot_window = tk.Toplevel(self.master)
plot_window.title('生成图表')
plot_window.geometry('400x300')
tk.Label(plot_window, text='请选择班级(可选):').pack(pady=10)
class_var = tk.StringVar(plot_window)
class_menu = tk.OptionMenu(plot_window, class_var, *['所有班级']+list(self.data['班级'].unique()))
class_menu.pack()
tk.Label(plot_window, text='请选择学科:').pack(pady=10)
subject_var = tk.StringVar(plot_window, '语文')
tk.Radiobutton(plot_window, text='语文', variable=subject_var, value='语文').pack()
tk.Radiobutton(plot_window, text='数学', variable=subject_var, value='数学').pack()
tk.Radiobutton(plot_window, text='英语', variable=subject_var, value='英语').pack()
tk.Label(plot_window, text='请选择图表类型:').pack(pady=10)
chart_type_var = tk.StringVar(plot_window, '柱状图')
tk.Radiobutton(plot_window, text='柱状图', variable=chart_type_var, value='柱状图').pack()
tk.Radiobutton(plot_window, text='折线图', variable=chart_type_var, value='折线图').pack()
def plot():
class_name = class_var.get()
subject = subject_var.get()
chart_type = chart_type_var.get()
if class_name != '所有班级':
data = self.data[self.data['班级'] == class_name]
else:
data = self.data
self.plot_chart(data, subject, chart_type)
tk.Button(plot_window, text='生成图表', command=plot).pack(pady=10)
def plot_chart(self, data, subject, chart_type):
fig = plt.figure(figsize=(8, 6))
ax = fig.add_subplot(111)
if chart_type == '柱状图':
ax.bar(data['姓名'], data[subject])
elif chart_type == '折线图':
ax.plot(data['姓名'], data[subject])
ax.set_xlabel('学生姓名')
ax.set_ylabel(f'{subject}成绩')
ax.set_title(f'{subject}成绩图表')
canvas = FigureCanvasTkAgg(fig, master=self.master)
canvas.draw()
canvas.get_tk_widget().pack(pady=20)
def grade_table(self):
for widget in self.grade_table.winfo_children():
widget.destroy()
if self.current_class is not None:
data = self.data.loc[self.data['班级'] == self.current_class]
else:
data = self.data
table = tk.Frame(self.grade_table)
table.pack()
for i, col in enumerate(data.columns):
label = tk.Label(table, text=col, font=('Arial', 10, 'bold'), width=10, relief='solid', borderwidth=1)
label.grid(row=0, column=i, padx=5, pady=5)
for i, row in data.iterrows():
for j, value in enumerate(row):
label = tk.Label(table, text=value, font=('Arial', 10), width=10, relief='solid', borderwidth=1)
label.grid(row=i+1, column=j, padx=5, pady=5)
root = tk.Tk() app = GradeManagementSystem(root) root.mainloop()
原文地址: http://www.cveoy.top/t/topic/oRIX 著作权归作者所有。请勿转载和采集!