使用模块要求:
tkinter、numpy、openpyxl、matplotlib、pymysql、re、time;其中matplotlib用于绘制统计图
开发工具:pycharm专业版、python3.7、mysql8.0
需要咨询、源码、定做、QQ扫码加:
https://img-mid.csdnimg.cn/release/static/image/mid/ask/153137086786150.jpg
点击此处链接、并扫描加QQ好友
需要咨询、源码、定做课设(C语言数据结构、python)
加QQ:3125841747
更对课设请访问CSDN主页,直达链接:https://blog.csdn.net/m0_56604317?spm=1000.2115.3001.5343
运行效果:
主页面:
教师端主要功能:
教师端登录后的效果——个人资料页面:
教师端登录后的效果——学生查询页面:
教师端登录后的效果——成绩查询页面:
教师端登录后的效果——成绩分析页面:
成绩分析页面——课程成绩分析(统计图):
各班级创建分析页面——统计图:
班级综合成绩评定页面——扇形统计图:
修改密码页面:
课程管理页面——根据学院、考试方式进行添加或删除课程:
Teacherpage.py页面代码如下:
from tkinter import * from tkinter import messagebox, filedialog from tkinter.ttk import * import openpyxl as openpyxl import AddCoursePage import AddScorePage import ClassGradeAnalysis import ComprehensivePerformanceEvaluation import CourseScoreAnalysis import Dao import DeleteCoursePage import DeleteScorePage import Login import UpdateCoursePage import AddStudentPage import DeleteStudentPage import UpdateScorePage import UpdateStudentPage import numpy as np import matplotlib.pyplot as plt class WinGUI(Tk): def __init__(self): super().__init__() self.__win() self.tk_label_title = self.__tk_label_title() self.tk_label_current_user = self.__tk_label_current_user() self.tk_tabs_content = Frame_content(self) self.tk_button_logout_user = self.__tk_button_logout_user() def __win(self): self.title("教师端") # 设置窗口大小、居中 width = 1000 height = 600 screenwidth = self.winfo_screenwidth() screenheight = self.winfo_screenheight() geometry = '%dx%d+%d+%d' % (width, height, (screenwidth - width) / 2, (screenheight - height) / 2) self.geometry(geometry) self.resizable(width=False, height=False) self.iconbitmap('logo.ico') def __tk_label_title(self): label = Label(self, text="学生成绩管理系统", anchor="center") label.place(x=0, y=0, width=800, height=100) return label def __tk_label_current_user(self): label = Label(self, text="当前用户:admin", anchor="center") label.place(x=800, y=70, width=150, height=30) return label def __tk_button_logout_user(self): btn = Button(self, text="退出") btn.place(x=950, y=70, width=50, height=30) return btn class Frame_content(Notebook): def __init__(self, parent): super().__init__(parent) self.__frame() def __frame(self): self.tk_tabs_content_0 = Frame_content_0(self) self.add(self.tk_tabs_content_0, text="个人资料") self.tk_tabs_content_1 = Frame_content_1(self) self.add(self.tk_tabs_content_1, text="学生查询") self.tk_tabs_content_2 = Frame_content_2(self) self.add(self.tk_tabs_content_2, text="成绩查询") self.tk_tabs_content_3 = Frame_content_3(self) self.add(self.tk_tabs_content_3, text="成绩分析") self.tk_tabs_content_4 = Frame_content_4(self) self.add(self.tk_tabs_content_4, text="修改密码") self.tk_tabs_content_5 = Frame_content_5(self) self.add(self.tk_tabs_content_5, text="课程管理") self.place(x=0, y=100, width=1000, height=500) class Frame_content_0(Frame): def __init__(self, parent): super().__init__(parent) self.__frame() self.tk_label_tea_number = self.__tk_label_tea_number() self.tk_input_tea_number = self.__tk_input_tea_number() self.tk_label_tea_name = self.__tk_label_tea_name() self.tk_input_tea_name = self.__tk_input_tea_name() self.tk_label_tea_gender = self.__tk_label_tea_gender() self.tk_select_tea_gender = self.__tk_select_tea_gender() self.tk_label_tea_identity = self.__tk_label_tea_identity() self.tk_input_tea_identity = self.__tk_input_tea_identity() self.tk_label_tea_email = self.__tk_label_tea_email() self.tk_input_tea_email = self.__tk_input_tea_email() self.tk_button_tea_update = self.__tk_button_tea_update() self.tk_button_tea_reset = self.__tk_button_tea_reset() def __frame(self): self.place(x=0, y=100, width=1000, height=500) def __tk_label_tea_number(self): label = Label(self, text="工号", anchor="e") label.place(x=360, y=40, width=100, height=30) return label def __tk_input_tea_number(self): self.tea_number = StringVar(self) ipt = Entry(self, text=self.tea_number) ipt.place(x=490, y=40, width=150, height=30) ipt.config(stat='disable') return ipt def __tk_label_tea_name(self): label = Label(self, text="姓名", anchor="e") label.place(x=360, y=110, width=100, height=30) return label def __tk_input_tea_name(self): self.tea_name = StringVar(self) ipt = Entry(self, text=self.tea_name) ipt.place(x=490, y=110, width=150, height=30) return ipt def __tk_label_tea_gender(self): label = Label(self, text="性别", anchor="e") label.place(x=360, y=180, width=100, height=30) return label def __tk_select_tea_gender(self): cb = Combobox(self, state='readonly') cb['values'] = ("男", "女") cb.place(x=490, y=180, width=150, height=30) return cb def __tk_label_tea_identity(self): label = Label(self, text="身份证号", anchor="e") label.place(x=360, y=250, width=100, height=30) return label def __tk_input_tea_identity(self): self.tea_identify = StringVar(self) ipt = Entry(self, text=self.tea_identify) ipt.place(x=490, y=250, width=150, height=30) return ipt def __tk_label_tea_email(self): label = Label(self, text="电子邮箱", anchor="e") label.place(x=360, y=320, width=100, height=30) return label def __tk_input_tea_email(self): self.tea_email = StringVar(self) ipt = Entry(self, text=self.tea_email) ipt.place(x=490, y=320, width=150, height=30) return ipt def __tk_button_tea_update(self): btn = Button(self, text="修改") btn.place(x=400, y=390, width=80, height=30) return btn def __tk_button_tea_reset(self): btn = Button(self, text="重置") btn.place(x=520, y=390, width=80, height=30) return btn class Frame_content_1(Frame): def __init__(self, parent): super().__init__(parent) self.__frame() self.tk_table_student_query = self.__tk_table_student_query() self.tk_input_stu_name = self.__tk_input_stu_name() self.tk_select_box_stu_gender = self.__tk_select_box_stu_gender() self.tk_button_stu_search = self.__tk_button_stu_search() self.tk_button_addStudent = self.__tk_button_addStudent() self.tk_button_delete_student = self.__tk_button_delete_student() self.tk_button_stu_refresh = self.__tk_button_stu_refresh() self.tk_button_studentinfo_export = self.__tk_button_studentinfo_export() def __frame(self): self.place(x=0, y=100, width=1000, height=500) def __tk_table_student_query(self): # 表头字段 表头宽度 self.tk_table_student_manage_columns = {"ID": 50, "学号": 100, "姓名": 150, '性别': 100, '身份证号': 300, '班级': 100, '邮箱': 200} # 初始化表格 表格是基于Treeview,tkinter本身没有表格。show="headings" 为隐藏首列。 tk_table = Treeview(self, show="headings", columns=list(self.tk_table_student_manage_columns)) for text, width in self.tk_table_student_manage_columns.items(): # 批量设置列属性 tk_table.heading(text, text=text, anchor='center') tk_table.column(text, anchor='center', width=width, stretch=False) # stretch 不自动拉伸 # 插入数据示例 # # # 导入初始数据 self.tk_student_table_dataset = Dao.getAllStudents() if self.tk_student_table_dataset.get("code") == 0: if self.tk_student_table_dataset.get("data"): print(self.tk_student_table_dataset.get("data")) for values in self.tk_student_table_dataset.get("data"): tk_table.insert('', END, values=list(values.values())) else: print("未查询到数据!") else: print("数据查询异常!") tk_table.place(x=0, y=60, width=1000, height=415) return tk_table def __tk_input_stu_name(self): ipt = Entry(self) ipt.place(x=360, y=10, width=150, height=30) return ipt def __tk_select_box_stu_gender(self): cb = Combobox(self, state="readonly") cb['values'] = ("请选择性别", "男", "女") cb.place(x=540, y=10, width=150, height=30) cb.current(0) return cb def __tk_button_stu_search(self): btn = Button(self, text="搜索") btn.place(x=720, y=10, width=70, height=30) return btn def __tk_button_stu_refresh(self): btn = Button(self, text="刷新") btn.place(x=820, y=10, width=70, height=30) return btn def __tk_button_addStudent(self): btn = Button(self, text="添加学生") btn.place(x=50, y=10, width=100, height=30) return btn def __tk_button_delete_student(self): btn = Button(self, text="删除学生") btn.place(x=180, y=10, width=100, height=30) return btn def __tk_button_studentinfo_export(self): btn = Button(self, text="导出") btn.place(x=920, y=10, width=50, height=30) return btn class Frame_content_2(Frame): def __init__(self, parent): super().__init__(parent) self.__frame() self.tk_table_stu_score = self.__tk_table_stu_score() self.tk_button_add_score = self.__tk_button_add_score() self.tk_button_delete_score = self.__tk_button_delete_score() self.tk_select_box_score_course_name = self.__tk_select_box_score_course_name() self.tk_select_box_score_nature = self.__tk_select_box_score_nature() self.tk_select_box_score_department = self.__tk_select_box_score_department() self.tk_button_stu_score_search = self.__tk_button_stu_score_search() self.tk_button_stu_score_export = self.__tk_button_stu_score_export() def __frame(self): self.place(x=0, y=100, width=1000, height=500) def __tk_table_stu_score(self): # 表头字段 表头宽度 self.tk_table_stu_score_columns = {"#": 50, "学号": 70, "姓名": 80, "课程名称": 200, "课程性质": 100, "开课学院": 270, "考试方式": 80, "学分": 50, "成绩": 100} # 初始化表格 表格是基于Treeview,tkinter本身没有表格。show="headings" 为隐藏首列。 tk_table = Treeview(self, show="headings", columns=list(self.tk_table_stu_score_columns)) for text, width in self.tk_table_stu_score_columns.items(): # 批量设置列属性 tk_table.heading(text, text=text, anchor='center') tk_table.column(text, anchor='center', width=width, stretch=False) # stretch 不自动拉伸 # 插入数据示例 self.tk_score_table_dataset = Dao.searchStudentScore() # 导入初始数据 if self.tk_score_table_dataset.get("code") == 0 and self.tk_score_table_dataset.get("data"): for data in self.tk_score_table_dataset.get("data"): tk_table.insert('', END, values=list(data.values())) tk_table.place(x=0, y=60, width=1000, height=415) return tk_table def __tk_button_add_score(self): btn = Button(self, text="添加成绩") btn.place(x=50, y=10, width=100, height=30) return btn def __tk_button_delete_score(self): btn = Button(self, text="删除成绩") btn.place(x=170, y=10, width=100, height=30) return btn def __tk_select_box_score_course_name(self): cb = Combobox(self, state="readonly") values = ["请选择课程名称"] for i in Dao.getAllCourses().get("data"): values.append(i.get("cname")) cb['values'] = values cb.current(0) cb.place(x=290, y=10, width=150, height=30) return cb def __tk_select_box_score_nature(self): cb = Combobox(self, state="readonly") values = ["请选择课程性质"] for i in Dao.getDataDictByType("nature").get("data"): values.append(i.get("v")) cb['values'] = values cb.current(0) cb.place(x=460, y=10, width=150, height=30) return cb def __tk_select_box_score_department(self): cb = Combobox(self, state="readonly") values = ["请选择开课学院"] for i in Dao.getAllDepartments().get("data"): values.append(i.get("v")) cb['values'] = values cb.current(0) cb.place(x=630, y=10, width=150, height=30) return cb def __tk_button_stu_score_search(self): btn = Button(self, text="搜索") btn.place(x=800, y=10, width=70, height=30) return btn def __tk_button_stu_score_export(self): btn = Button(self, text="导出") btn.place(x=890, y=10, width=70, height=30) return btn class Frame_content_3(Frame): def __init__(self, parent): super().__init__(parent) self.__frame() self.tk_button_pieChart = self.__tk_button_pieChart() self.tk_button_columnChart = self.__tk_button_columnChart() self.tk_button_paratacticColumnChart = self.__tk_button_paratacticColumnChart() def __frame(self): self.place(x=0, y=100, width=1000, height=500) def __tk_button_columnChart(self): btn = Button(self, text="课程成绩分析") btn.place(x=80, y=50, width=150, height=70) return btn def __tk_button_paratacticColumnChart(self): btn = Button(self, text="班级成绩分析") btn.place(x=420, y=50, width=150, height=70) return btn def __tk_button_pieChart(self): btn = Button(self, text="综合成绩评定") btn.place(x=760, y=50, width=150, height=70) return btn class Frame_content_4(Frame): def __init__(self, parent): super().__init__(parent) self.__frame() self.tk_label_original_pwd = self.__tk_label_original_pwd() self.tk_input_original_pwd = self.__tk_input_original_pwd() self.tk_label_new_pwd = self.__tk_label_new_pwd() self.tk_input_new_pwd = self.__tk_input_new_pwd() self.tk_label_confirm_pwd = self.__tk_label_confirm_pwd() self.tk_input_confirm_pwd = self.__tk_input_confirm_pwd() self.tk_button_update_tea_pwd = self.__tk_button_update_tea_pwd() def __frame(self): self.place(x=0, y=100, width=1000, height=500) def __tk_label_original_pwd(self): label = Label(self, text="原密码", anchor="e") label.place(x=360, y=40, width=100, height=30) return label def __tk_input_original_pwd(self): ipt = Entry(self, show='*') ipt.place(x=490, y=40, width=150, height=30) return ipt def __tk_label_new_pwd(self): label = Label(self, text="新密码", anchor="e") label.place(x=360, y=110, width=100, height=30) return label def __tk_input_new_pwd(self): ipt = Entry(self, show='*') ipt.place(x=490, y=110, width=150, height=30) return ipt def __tk_label_confirm_pwd(self): label = Label(self, text="确认密码", anchor="e") label.place(x=360, y=180, width=100, height=30) return label def __tk_input_confirm_pwd(self): ipt = Entry(self, show='*') ipt.place(x=490, y=180, width=150, height=30) return ipt def __tk_button_update_tea_pwd(self): btn = Button(self, text="修改") btn.place(x=450, y=260, width=100, height=30) return btn class Frame_content_5(Frame): def __init__(self, parent): super().__init__(parent) self.__frame() self.tk_table_course_manage = self.__tk_table_course_manage() self.tk_button_add_course = self.__tk_button_add_course() self.tk_button_delete_course = self.__tk_button_delete_course() self.tk_select_box_course_department = self.__tk_select_box_course_department() self.tk_select_box_course_exam_method = self.__tk_select_box_course_exam_method() self.tk_button_course_search = self.__tk_button_course_search() self.tk_button_course_export = self.__tk_button_course_export() def __frame(self): self.place(x=0, y=100, width=1000, height=500) def __tk_table_course_manage(self): # 表头字段 表头宽度 self.tk_table_course_manage_columns = {"课程号": 100, "课程名称": 200, "学分": 100, "课程性质": 200, "开课学院": 300, "考试方式": 100} # 初始化表格 表格是基于Treeview,tkinter本身没有表格。show="headings" 为隐藏首列。 tk_table = Treeview(self, show="headings", columns=list(self.tk_table_course_manage_columns)) for text, width in self.tk_table_course_manage_columns.items(): # 批量设置列属性 tk_table.heading(text, text=text, anchor='center') tk_table.column(text, anchor='center', width=width, stretch=False) # stretch 不自动拉伸 # 插入数据示例 self.tk_course_table_dataset = Dao.getAllCourses() # 导入初始数据 if self.tk_course_table_dataset.get("code") == 0 and self.tk_course_table_dataset.get("data"): for data in self.tk_course_table_dataset.get("data"): tk_table.insert('', END, values=list(data.values())) tk_table.place(x=0, y=60, width=1000, height=415) return tk_table def __tk_button_add_course(self): btn = Button(self, text="添加课程") btn.place(x=50, y=10, width=100, height=30) return btn def __tk_button_delete_course(self): btn = Button(self, text="删除课程") btn.place(x=180, y=10, width=100, height=30) return btn def __tk_select_box_course_department(self): cb = Combobox(self, state="readonly") values = ["请选择开课学院"] for i in Dao.getAllDepartments().get("data"): values.append(i.get("v")) cb['values'] = values cb.current(0) cb.place(x=310, y=10, width=150, height=30) return cb def __tk_select_box_course_exam_method(self): cb = Combobox(self, state="readonly") values = ["请选择考试方式"] for i in Dao.getDataDictByType("exammethod").get("data"): values.append(i.get("v")) cb['values'] = values cb.current(0) cb.place(x=490, y=10, width=150, height=30) return cb def __tk_button_course_search(self): btn = Button(self, text="搜索") btn.place(x=670, y=10, width=100, height=30) return btn def __tk_button_course_export(self): btn = Button(self, text="导出") btn.place(x=800, y=10, width=100, height=30) return btn class Win(WinGUI): def __init__(self, current_user): super().__init__() self.__event_bind() self.current_user = current_user self.uid = current_user.get("uid") self.tk_label_current_user['text'] = "当前用户:" + current_user.get("uname") self.tk_tabs_content.tk_tabs_content_0.tea_number.set(current_user.get("uid")) self.tk_tabs_content.tk_tabs_content_0.tea_name.set(current_user.get("uname")) self.tk_tabs_content.tk_tabs_content_0.tk_select_tea_gender.current(0 if current_user.get("ugender") == '男' else 1) self.tk_tabs_content.tk_tabs_content_0.tea_identify.set(current_user.get("uidentify")) self.tk_tabs_content.tk_tabs_content_0.tea_email.set(current_user.get("uemail")) def logout(self): try: self.updateStudent.destroy() self.addInfo.destroy() self.delete.destroy() except Exception as e: print(e) messagebox.showwarning('提示', '欢迎下次使用!') self.destroy() login = Login.Win() login.mainloop() def updateStudentInfo(self, evt): current_focus = self.tk_tabs_content.tk_tabs_content_1.tk_table_student_query.focus() current_studentinfo = self.tk_tabs_content.tk_tabs_content_1.tk_table_student_query.set(current_focus) current_uid = current_studentinfo.get('学号') self.updateStudent = UpdateStudentPage.Win(current_uid) self.updateStudent.mainloop() print("<<TreeviewSelect>>事件未处理", evt) def updateTeacherInfo(self, evt): __tea_name = self.tk_tabs_content.tk_tabs_content_0.tk_input_tea_name.get() __tea_gender = self.tk_tabs_content.tk_tabs_content_0.tk_select_tea_gender.get() __tea_identify = self.tk_tabs_content.tk_tabs_content_0.tk_input_tea_identity.get() __tea_email = self.tk_tabs_content.tk_tabs_content_0.tk_input_tea_email.get() if not __tea_name or not __tea_gender or not __tea_identify or not __tea_email: messagebox.showinfo("提示", "必填项不能为空!") return if not re.match(r'^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$', __tea_identify): messagebox.showinfo("提示", "身份证格式不合法!") return if not re.match(r'^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$', __tea_email): messagebox.showinfo("提示", "电子邮箱格式不合法!") return res = Dao.updateUser(self.uid, __tea_name, __tea_gender, __tea_identify, 0, __tea_email) messagebox.showinfo("提示", res.get("msg")) self.tk_label_current_user['text'] = "当前用户:" + __tea_name print("更新教师信息", evt) def resetTeacherInfo(self, evt): self.tk_tabs_content.tk_tabs_content_0.tea_name.set(self.current_user.get("uname")) self.tk_tabs_content.tk_tabs_content_0.tk_select_tea_gender.current(0 if self.current_user.get("ugender") == '男' else 1) self.tk_tabs_content.tk_tabs_content_0.tea_identify.set(self.current_user.get("uidentify")) self.tk_tabs_content.tk_tabs_content_0.tea_email.set(self.current_user.get("uemail")) print("重置教师信息", evt) def searchStudentInfo(self, evt): for _ in map(self.tk_tabs_content.tk_tabs_content_1.tk_table_student_query.delete, self.tk_tabs_content.tk_tabs_content_1.tk_table_student_query.get_children("")): pass value = self.tk_tabs_content.tk_tabs_content_1.tk_input_stu_name.get() num = self.tk_tabs_content.tk_tabs_content_1.tk_select_box_stu_gender.get() print(num, value) if num == '请选择性别': result = Dao.searchStudents(value, '') else: result = Dao.searchStudents(value, num) if result.get("code") == 0: if result.get("data"): # print(result.get("data")) for values in result.get("data"): self.tk_tabs_content.tk_tabs_content_1.tk_table_student_query.insert('', END, values=list(values.values())) else: print("未查询到数据!") else: print("数据查询异常!") print("搜索学生信息", evt) def updateStudentScore(self, evt): current_item = self.tk_tabs_content.tk_tabs_content_2.tk_table_stu_score.set(self.tk_tabs_content.tk_tabs_content_2.tk_table_stu_score.focus()) data = { "uid": current_item.get("学号"), "cname": current_item.get("课程名称"), "score": current_item.get("成绩") } updateScorePage = UpdateScorePage.Win(data) updateScorePage.mainloop() print("修改学生课程成绩", evt) def searchStuScore(self, evt): __score_manage = self.tk_tabs_content.tk_tabs_content_2 __course_name = __score_manage.tk_select_box_score_course_name.get() __course_nature = __score_manage.tk_select_box_score_nature.get() __course_department = __score_manage.tk_select_box_score_department.get() if __score_manage.tk_select_box_score_course_name.current() == 0: __course_name = '' if __score_manage.tk_select_box_score_nature.current() == 0: __course_nature = '' if __score_manage.tk_select_box_score_department.current() == 0: __course_department = '' for _ in map(__score_manage.tk_table_stu_score.delete, __score_manage.tk_table_stu_score.get_children("")): pass __score_manage.tk_score_table_dataset = Dao.searchStudentScore(__course_name, __course_nature, __course_department) # 导入初始数据 if __score_manage.tk_score_table_dataset.get("code") == 0 and __score_manage.tk_score_table_dataset.get("data"): for data in __score_manage.tk_score_table_dataset.get("data"): __score_manage.tk_table_stu_score.insert('', END, values=list(data.values())) __score_manage.tk_select_box_score_course_name.current(0) __score_manage.tk_select_box_score_nature.current(0) __score_manage.tk_select_box_score_department.current(0) print("搜索学生成绩!") def exportStuScore(self, evt): path = filedialog.askdirectory() try: book = openpyxl.Workbook() sheet = book.active fff = list(self.tk_tabs_content.tk_tabs_content_2.tk_table_stu_score_columns.keys()) # 获取表头信息 sheet.append(fff) dataset = [list(data_item.values()) for data_item in self.tk_tabs_content.tk_tabs_content_2.tk_score_table_dataset.get("data")] print(dataset) for i in dataset: sheet.append(i) book.save(f"{path}/student_score.xlsx") messagebox.showinfo("提示", "导出成功!") except Exception as e: messagebox.showinfo("提示", "导出失败!") print(e) print("导出学生成绩!", evt) def addStudentInfo(self, evt): self.addInfo = AddStudentPage.Win() self.addInfo.mainloop() print("<Button-1>事件未处理", evt) def deleteStudentInfo(self, evt): self.delete = DeleteStudentPage.Win() self.delete.mainloop() print("<Button-1>事件未处理", evt) def addStudentScore(self, evt): addScorePage = AddScorePage.Win() addScorePage.mainloop() def deleteStudentScore(self, evt): deleteScorePage = DeleteScorePage.Win() deleteScorePage.mainloop() print("删除学生成绩", evt) def updateTeacherPassword(self, evt): __original_pwd = self.tk_tabs_content.tk_tabs_content_4.tk_input_original_pwd.get() __new_pwd = self.tk_tabs_content.tk_tabs_content_4.tk_input_new_pwd.get() __confirm_pwd = self.tk_tabs_content.tk_tabs_content_4.tk_input_confirm_pwd.get() if __original_pwd == '' or __new_pwd == '' or __confirm_pwd == '': messagebox.showwarning("提示", "必填项未填写!") return if not re.match(r"^[0-9a-zA-Z~!@#$%^&*._?]{6,18}$", __original_pwd) \ or not re.match(r"^[0-9a-zA-Z~!@#$%^&*._?]{6,18}$", __new_pwd) \ or not re.match(r"^[0-9a-zA-Z~!@#$%^&*._?]{6,18}$", __confirm_pwd): messagebox.showwarning("提示", "密码格式应为6-18位数字、字母、特殊字符的组合!") return if __new_pwd != __confirm_pwd: messagebox.showwarning("提示", "两次密码输入不一致") return res = Dao.updatePassword(self.uid, __original_pwd, __new_pwd) messagebox.showinfo("提示", res.get("msg")) if res.get("code") == 0: self.destroy() login = Login.Win() login.mainloop() print("修改教师密码", evt) def addCourseInfo(self, evt): addCoursePage = AddCoursePage.Win() addCoursePage.mainloop() print("添加成绩!") def deleteCourseInfo(self, evt): deleteCoursePage = DeleteCoursePage.Win() deleteCoursePage.mainloop() print("删除课程!") def searchCourseInfo(self, evt): __course_manage = self.tk_tabs_content.tk_tabs_content_5 __department = __course_manage.tk_select_box_course_department.get() __exammethod = __course_manage.tk_select_box_course_exam_method.get() if __course_manage.tk_select_box_course_department.current() == 0: __department = '' if __course_manage.tk_select_box_course_exam_method.current() == 0: __exammethod = '' for _ in map(__course_manage.tk_table_course_manage.delete, __course_manage.tk_table_course_manage.get_children("")): pass self.tk_tabs_content.tk_tabs_content_5.tk_course_table_dataset = Dao.searchCourses(__department, __exammethod) # 导入初始数据 if self.tk_tabs_content.tk_tabs_content_5.tk_course_table_dataset.get("code") == 0 and self.tk_tabs_content.tk_tabs_content_5.tk_course_table_dataset.get("data"): for data in self.tk_tabs_content.tk_tabs_content_5.tk_course_table_dataset.get("data"): __course_manage.tk_table_course_manage.insert('', END, values=list(data.values())) __course_manage.tk_select_box_course_department.current(0) __course_manage.tk_select_box_course_exam_method.current(0) print("查询课程!") def updateCourseInfo(self, evt): __focus = self.tk_tabs_content.tk_tabs_content_5.tk_table_course_manage.focus() current_item = self.tk_tabs_content.tk_tabs_content_5.tk_table_course_manage.set(__focus) __cid = current_item.get("课程号") self.updateCoursePage = UpdateCoursePage.Win(__cid) self.updateCoursePage.mainloop() print("更新课程信息!") def exportCourseInfo(self, evt): path = filedialog.askdirectory() try: book = openpyxl.Workbook() sheet = book.active fff = list(self.tk_tabs_content.tk_tabs_content_5.tk_table_course_manage_columns.keys()) # 获取表头信息 sheet.append(fff) dataset = [list(data_item.values()) for data_item in self.tk_tabs_content.tk_tabs_content_5.tk_course_table_dataset.get("data")] print(dataset) for i in dataset: sheet.append(i) book.save(path + "/course_info.xlsx") messagebox.showinfo("提示", "导出成功!") except Exception as e: messagebox.showinfo("提示", "导出失败!") print(e) def logout_user(self, evt): messagebox.showwarning('提示', '欢迎下次使用!') self.destroy() login = Login.Win() login.mainloop() def studentinfo_refresh(self, evt): # 删除原结点,加入新结点 for _ in map(self.tk_tabs_content.tk_tabs_content_1.tk_table_student_query.delete, self.tk_tabs_content.tk_tabs_content_1.tk_table_student_query.get_children("")): pass result = Dao.getAllStudents() if result.get("code") == 0: if result.get("data"): # print(result.get("data")) for values in result.get("data"): self.tk_tabs_content.tk_tabs_content_1.tk_table_student_query.insert('', END, values=list(values.values())) else: print("未查询到数据!") else: print("数据查询异常!") def studentinfo_export(self, evt): path = filedialog.askdirectory() try: book = openpyxl.Workbook() sheet = book.active fff = list(self.tk_tabs_content.tk_tabs_content_1.tk_table_student_manage_columns.keys()) # 获取表头信息 sheet.append(fff) dataset = [list(data_item.values()) for data_item in self.tk_tabs_content.tk_tabs_content_1.tk_student_table_dataset.get("data")] print(dataset) for i in dataset: sheet.append(i) book.save(path + "/student_info.xlsx") messagebox.showinfo("提示", "导出成功!") except Exception as e: messagebox.showinfo("提示", "导出失败!") print(e) def columnChart(self, evt): courseScoreAnalysis = CourseScoreAnalysis.Win() courseScoreAnalysis.mainloop() def paratacticColumnChart(self, evt): classGradeAnalysis = ClassGradeAnalysis.Win() classGradeAnalysis.mainloop() def pieChart(self, evt): comprehensivePerformanceEvaluation = ComprehensivePerformanceEvaluation.Win() comprehensivePerformanceEvaluation.mainloop() def __event_bind(self): self.protocol('WM_DELETE_WINDOW', self.logout) self.tk_tabs_content.tk_tabs_content_1.tk_table_student_query.bind('<<TreeviewSelect>>', self.updateStudentInfo) self.tk_tabs_content.tk_tabs_content_0.tk_button_tea_update.bind('<Button-1>', self.updateTeacherInfo) self.tk_tabs_content.tk_tabs_content_0.tk_button_tea_reset.bind('<Button-1>', self.resetTeacherInfo) self.tk_tabs_content.tk_tabs_content_1.tk_button_stu_search.bind('<Button-1>', self.searchStudentInfo) self.tk_tabs_content.tk_tabs_content_1.tk_button_addStudent.bind('<Button-1>', self.addStudentInfo) self.tk_tabs_content.tk_tabs_content_1.tk_button_delete_student.bind('<Button-1>', self.deleteStudentInfo) self.tk_tabs_content.tk_tabs_content_1.tk_button_stu_refresh.bind('<Button-1>', self.studentinfo_refresh) self.tk_tabs_content.tk_tabs_content_1.tk_button_studentinfo_export.bind('<Button-1>', self.studentinfo_export) self.tk_tabs_content.tk_tabs_content_2.tk_button_add_score.bind('<Button-1>', self.addStudentScore) self.tk_tabs_content.tk_tabs_content_2.tk_button_delete_score.bind('<Button-1>', self.deleteStudentScore) self.tk_tabs_content.tk_tabs_content_2.tk_table_stu_score.bind('<<TreeviewSelect>>', self.updateStudentScore) self.tk_tabs_content.tk_tabs_content_2.tk_button_stu_score_search.bind('<Button-1>', self.searchStuScore) self.tk_tabs_content.tk_tabs_content_2.tk_button_stu_score_export.bind('<Button-1>', self.exportStuScore) self.tk_tabs_content.tk_tabs_content_3.tk_button_columnChart.bind('<Button-1>', self.columnChart) self.tk_tabs_content.tk_tabs_content_3.tk_button_paratacticColumnChart.bind('<Button-1>', self.paratacticColumnChart) self.tk_tabs_content.tk_tabs_content_3.tk_button_pieChart.bind('<Button-1>', self.pieChart) self.tk_tabs_content.tk_tabs_content_4.tk_button_update_tea_pwd.bind('<Button-1>', self.updateTeacherPassword) self.tk_tabs_content.tk_tabs_content_5.tk_button_add_course.bind('<Button-1>', self.addCourseInfo) self.tk_tabs_content.tk_tabs_content_5.tk_button_delete_course.bind('<Button-1>', self.deleteCourseInfo) self.tk_tabs_content.tk_tabs_content_5.tk_button_course_search.bind('<Button-1>', self.searchCourseInfo) self.tk_tabs_content.tk_tabs_content_5.tk_button_course_export.bind('<Button-1>', self.exportCourseInfo) self.tk_tabs_content.tk_tabs_content_5.tk_table_course_manage.bind('<<TreeviewSelect>>', self.updateCourseInfo) self.tk_button_logout_user.bind('<Button-1>', self.logout_user)学生端登录页面效果:
学生端——修改密码:
学生端代码如下:
student.py:
from tkinter import * from tkinter import messagebox, filedialog from tkinter.ttk import * import numpy as np import openpyxl from matplotlib import pyplot as plt import Dao import Login global current_uid class WinGUI(Tk): def __init__(self): super().__init__() self.__win() self.tk_label_title = self.__tk_label_title() self.tk_label_current_user = self.__tk_label_current_user() self.tk_tabs_content = Frame_content(self) self.tk_button_logout = self.__tk_button_logout() def __win(self): self.title("成绩查询") # 设置窗口大小、居中 width = 1000 height = 600 screenwidth = self.winfo_screenwidth() screenheight = self.winfo_screenheight() geometry = '%dx%d+%d+%d' % (width, height, (screenwidth - width) / 2, (screenheight - height) / 2) self.geometry(geometry) self.resizable(width=False, height=False) self.iconbitmap('logo.ico') def __tk_label_title(self): label = Label(self, text="学生成绩管理系统", anchor="center") label.place(x=0, y=0, width=800, height=100) return label def __tk_label_current_user(self): label = Label(self, text="当前用户:admin", anchor="center") label.place(x=800, y=70, width=150, height=30) return label def __tk_button_logout(self): btn = Button(self, text="退出") btn.place(x=950, y=70, width=50, height=30) return btn class Frame_content(Notebook): def __init__(self, parent): super().__init__(parent) self.__frame() def __frame(self): self.tk_tabs_content_0 = Frame_content_0(self) self.add(self.tk_tabs_content_0, text="个人资料") self.tk_tabs_content_1 = Frame_content_1(self) self.add(self.tk_tabs_content_1, text="成绩查询") self.tk_tabs_content_3 = Frame_content_3(self) self.add(self.tk_tabs_content_3, text="修改密码") self.place(x=0, y=100, width=1000, height=500) class Frame_content_0(Frame): def __init__(self, parent): super().__init__(parent) self.__frame() self.tk_label_stu_number = self.__tk_label_stu_number() self.tk_input_stu_number = self.__tk_input_stu_number() self.tk_label_stu_name = self.__tk_label_stu_name() self.tk_input_stu_name = self.__tk_input_stu_name() self.tk_label_stu_gender = self.__tk_label_stu_gender() self.tk_tk_select_stu_gender = self.__tk_select_stu_gender() self.tk_label_stu_identity = self.__tk_label_stu_identity() self.tk_input_stu_identity = self.__tk_input_stu_identity() self.tk_label_stu_email = self.__tk_label_stu_email() self.tk_input_stu_email = self.__tk_input_stu_email() self.tk_button_stu_update = self.__tk_button_stu_update() self.tk_button_stu_reset = self.__tk_button_stu_reset() def __frame(self): self.place(x=0, y=100, width=1000, height=500) def __tk_label_stu_number(self): label = Label(self, text="学号", anchor="e") label.place(x=360, y=40, width=100, height=30) return label def __tk_input_stu_number(self): self.student_number = StringVar(self) ipt = Entry(self, text=self.student_number) ipt.place(x=490, y=40, width=150, height=30) ipt.config(stat='disable') return ipt def __tk_label_stu_name(self): label = Label(self, text="姓名", anchor="e") label.place(x=360, y=110, width=100, height=30) return label def __tk_input_stu_name(self): self.student_name = StringVar(self) ipt = Entry(self, text=self.student_name) ipt.place(x=490, y=110, width=150, height=30) return ipt def __tk_label_stu_gender(self): label = Label(self, text="性别", anchor="e") label.place(x=360, y=180, width=100, height=30) return label def __tk_select_stu_gender(self): cb = Combobox(self, state='readonly') cb['values'] = ("男", "女") cb.place(x=490, y=180, width=150, height=30) return cb def __tk_label_stu_identity(self): label = Label(self, text="身份证号", anchor="e") label.place(x=360, y=250, width=100, height=30) return label def __tk_input_stu_identity(self): self.student_identify = StringVar(self) ipt = Entry(self, text=self.student_identify) ipt.place(x=490, y=250, width=150, height=30) return ipt def __tk_label_stu_email(self): label = Label(self, text="电子邮箱", anchor="e") label.place(x=360, y=320, width=100, height=30) return label def __tk_input_stu_email(self): self.student_email = StringVar(self) ipt = Entry(self, text=self.student_email) ipt.place(x=490, y=320, width=150, height=30) return ipt def __tk_button_stu_update(self): btn = Button(self, text="修改") btn.place(x=400, y=390, width=80, height=30) return btn def __tk_button_stu_reset(self): btn = Button(self, text="重置") btn.place(x=520, y=390, width=80, height=30) return btn class Frame_content_1(Frame): def __init__(self, parent): super().__init__(parent) self.__frame() self.tk_button_analysis = self.__tk_button_analysis() self.tk_table_stu_score = self.__tk_table_stu_score() self.tk_select_box_course_nature = self.__tk_select_box_course_nature() self.tk_select_box_course_department = self.__tk_select_box_course_department() self.tk_select_box_exam_method = self.__tk_select_box_exam_method() self.tk_button_search = self.__tk_button_search() self.tk_button_export = self.__tk_button_export() def __frame(self): self.place(x=0, y=100, width=1000, height=500) def __tk_table_stu_score(self): # 表头字段 表头宽度 self.tk_table_stu_score_columns = {"#": 50, "课程名称": 200, "课程性质": 150, "开课学院": 300, "考试方式": 100, "学分": 100, "成绩": 100} # 初始化表格 表格是基于Treeview,tkinter本身没有表格。show="headings" 为隐藏首列。 tk_table = Treeview(self, show="headings", columns=list(self.tk_table_stu_score_columns)) for text, width in self.tk_table_stu_score_columns.items(): # 批量设置列属性 tk_table.heading(text, text=text, anchor='center') tk_table.column(text, anchor='center', width=width, stretch=False) # stretch 不自动拉伸 # 插入数据示例 # self.tk_score_table_dataset = Dao.getScoreByUid(8888) # # 导入初始数据 # if self.tk_score_table_dataset.get("code") == 0 and self.tk_score_table_dataset.get("data"): # for data in self.tk_score_table_dataset.get("data"): # tk_table.insert('', END, values=list(data.values())) tk_table.place(x=0, y=55, width=1000, height=420) return tk_table def __tk_button_analysis(self): btn = Button(self, text="分析") btn.place(x=65, y=10, width=75, height=30) return btn def __tk_select_box_course_nature(self): cb = Combobox(self, state="readonly") values = ["请选择课程性质"] for i in Dao.getDataDictByType("nature").get("data"): values.append(i.get("v")) cb['values'] = values cb.current(0) cb.place(x=180, y=10, width=150, height=30) return cb def __tk_select_box_course_department(self): cb = Combobox(self, state="readonly") values = ["请选择开课学院"] for i in Dao.getAllDepartments().get("data"): values.append(i.get("v")) cb['values'] = values cb.current(0) cb.place(x=370, y=10, width=150, height=30) return cb def __tk_select_box_exam_method(self): cb = Combobox(self, state="readonly") values = ["请选择考试方式"] for i in Dao.getDataDictByType("exammethod").get("data"): values.append(i.get("v")) cb['values'] = values cb.current(0) cb.place(x=560, y=10, width=150, height=30) return cb def __tk_button_search(self): btn = Button(self, text="搜索") btn.place(x=750, y=10, width=75, height=30) return btn def __tk_button_export(self): btn = Button(self, text="导出") btn.place(x=840, y=10, width=75, height=30) return btn class Frame_content_3(Frame): def __init__(self, parent): super().__init__(parent) self.__frame() self.tk_label_original_password = self.__tk_label_original_password() self.tk_input_original_password = self.__tk_input_original_password() self.tk_label_new_password = self.__tk_label_new_password() self.tk_input_new_password = self.__tk_input_new_password() self.tk_label_confirm_password = self.__tk_label_confirm_password() self.tk_input_confirm_password = self.__tk_input_confirm_password() self.tk_button_update_stu_password = self.__tk_button_update_stu_password() def __frame(self): self.place(x=0, y=100, width=1000, height=500) def __tk_label_original_password(self): label = Label(self, text="原密码", anchor="e") label.place(x=360, y=40, width=100, height=30) return label def __tk_input_original_password(self): ipt = Entry(self, show='*') ipt.place(x=490, y=40, width=150, height=30) return ipt def __tk_label_new_password(self): label = Label(self, text="新密码", anchor="e") label.place(x=360, y=110, width=100, height=30) return label def __tk_input_new_password(self): ipt = Entry(self, show='*') ipt.place(x=490, y=110, width=150, height=30) return ipt def __tk_label_confirm_password(self): label = Label(self, text="确认密码", anchor="e") label.place(x=360, y=180, width=100, height=30) return label def __tk_input_confirm_password(self): ipt = Entry(self, show='*') ipt.place(x=490, y=180, width=150, height=30) return ipt def __tk_button_update_stu_password(self): btn = Button(self, text="修改") btn.place(x=460, y=250, width=100, height=30) return btn class Win(WinGUI): def __init__(self, current_user): super().__init__() self.__event_bind() self.uid = current_user.get("uid") self.uclid = current_user.get("uclid") self.tk_label_current_user['text'] = "当前用户:" + current_user.get("uname") self.tk_tabs_content.tk_tabs_content_0.student_number.set(current_user.get("uid")) self.tk_tabs_content.tk_tabs_content_0.student_name.set(current_user.get("uname")) self.tk_tabs_content.tk_tabs_content_0.tk_tk_select_stu_gender.current(0 if current_user.get("ugender") == '男' else 1) self.tk_tabs_content.tk_tabs_content_0.student_identify.set(current_user.get("uidentify")) self.tk_tabs_content.tk_tabs_content_0.student_email.set(current_user.get("uemail")) # 插入数据示例 self.score_table_dataset = Dao.getScoreByUid(self.uid) # 导入初始数据 if self.score_table_dataset.get("code") == 0 and self.score_table_dataset.get("data"): for data in self.score_table_dataset.get("data"): self.tk_tabs_content.tk_tabs_content_1.tk_table_stu_score.insert('', END, values=list(data.values())) def logout(self): messagebox.showwarning('提示', '欢迎下次使用!') self.destroy() login = Login.Win() login.mainloop() def updateStudentInfo(self, evt): __stu_name = self.tk_tabs_content.tk_tabs_content_0.tk_input_stu_name.get() __stu_gender = self.tk_tabs_content.tk_tabs_content_0.tk_tk_select_stu_gender.get() __stu_identify = self.tk_tabs_content.tk_tabs_content_0.tk_input_stu_identity.get() __stu_email = self.tk_tabs_content.tk_tabs_content_0.tk_input_stu_email.get() if not __stu_name or not __stu_gender or not __stu_identify or not __stu_email: messagebox.showinfo("提示", "必填项不能为空!") return if not re.match(r'^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$', __stu_identify): messagebox.showinfo("提示", "身份证格式不合法!") return if not re.match(r'^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$', __stu_email): messagebox.showinfo("提示", "电子邮箱格式不合法!") return res = Dao.updateUser(self.uid, __stu_name, __stu_gender, __stu_identify, self.uclid, __stu_email) messagebox.showinfo("提示", res.get("msg")) self.tk_label_current_user['text'] = "当前用户:" + __stu_name print("更新学生信息", evt) def stu_reset(self, evt): self.tk_tabs_content.tk_tabs_content_0.student_number.set(self.userInfo[0]) self.tk_tabs_content.tk_tabs_content_0.student_name.set(self.userInfo[1]) self.tk_tabs_content.tk_tabs_content_0.tk_tk_select_stu_gender.current(0 if self.userInfo[2] else 1) self.tk_tabs_content.tk_tabs_content_0.student_identify.set(self.userInfo[3]) self.tk_tabs_content.tk_tabs_content_0.student_email.set(self.userInfo[5]) def analysisStudentScore(self, evt): result = Dao.getScoreByUid(self.uid).get("data") plt.title('成绩统计图') # 设置x轴数据 x = [i.get("cname") for i in result] # 每组数据n有3个类型 total_width, n = 0.6, 3 width = total_width / n y1 = [i.get("score") for i in result] y2 = [i.get("avg_score") for i in Dao.getAllCourseAvgScore(self.uid).get("data")] plt.bar(x, y1, color="b", width=width, label='我的成绩') plt.plot(x, y2, color="g", label='科目平均成绩') # x和y轴标题 plt.xlabel("课程") plt.ylabel("分数") plt.legend(loc="best") plt.ylim((0, 100)) # 设置纵轴起始,终止和间距 my_y_ticks = np.arange(0, 100, 10) plt.yticks(my_y_ticks) plt.rcParams['font.sans-serif'] = ['SimHei'] # 支持中文显示 plt.show() print("成绩分析图表绘制") def searchStudentScore(self, evt): __score_query = self.tk_tabs_content.tk_tabs_content_1 __nature = __score_query.tk_select_box_course_nature.get() __department = __score_query.tk_select_box_course_department.get() __exammethod = __score_query.tk_select_box_exam_method.get() if __score_query.tk_select_box_course_nature.current() == 0: __nature = '' if __score_query.tk_select_box_course_department.current() == 0: __department = '' if __score_query.tk_select_box_exam_method.current() == 0: __exammethod = '' for _ in map(__score_query.tk_table_stu_score.delete, __score_query.tk_table_stu_score.get_children("")): pass self.score_table_dataset = Dao.getScoreByUid(self.uid, __nature, __department, __exammethod) # 导入初始数据 if self.score_table_dataset.get("code") == 0 and self.score_table_dataset.get("data"): for data in self.score_table_dataset.get("data"): __score_query.tk_table_stu_score.insert('', END, values=list(data.values())) __score_query.tk_select_box_course_nature.current(0) __score_query.tk_select_box_course_department.current(0) __score_query.tk_select_box_exam_method.current(0) print(f"查询学生{self.uid}的成绩!") def exportStudentScore(self, evt): path = filedialog.askdirectory() try: book = openpyxl.Workbook() sheet = book.active fff = list(self.tk_tabs_content.tk_tabs_content_1.tk_table_stu_score_columns.keys()) # 获取表头信息 sheet.append(fff) dataset = [list(data_item.values()) for data_item in self.score_table_dataset.get("data")] print(dataset) for i in dataset: sheet.append(i) book.save(f"{path}/{self.uid}.xlsx") messagebox.showinfo("提示", "导出成功!") except Exception as e: messagebox.showinfo("提示", "导出失败!") print(e) print("<Button-1>事件未处理", evt) def updateStudentPassword(self, evt): __original_pwd = self.tk_tabs_content.tk_tabs_content_3.tk_input_original_password.get() __new_pwd = self.tk_tabs_content.tk_tabs_content_3.tk_input_new_password.get() __confirm_pwd = self.tk_tabs_content.tk_tabs_content_3.tk_input_confirm_password.get() if __original_pwd == '' or __new_pwd == '' or __confirm_pwd == '': messagebox.showwarning("提示", "必填项未填写!") return if not re.match(r"^[0-9a-zA-Z~!@#$%^&*._?]{6,18}$", __original_pwd) \ or not re.match(r"^[0-9a-zA-Z~!@#$%^&*._?]{6,18}$", __new_pwd) \ or not re.match(r"^[0-9a-zA-Z~!@#$%^&*._?]{6,18}$", __confirm_pwd): messagebox.showwarning("提示", "密码格式应为6-18位数字、字母、特殊字符的组合!") return if __new_pwd != __confirm_pwd: messagebox.showwarning("提示", "两次密码输入不一致") return res = Dao.updatePassword(self.uid, __original_pwd, __new_pwd) messagebox.showinfo("提示", res.get("msg")) if res.get("code") == 0: self.destroy() login = Login.Win() login.mainloop() print("修改密码", evt) def logout_user(self, evt): messagebox.showwarning('提示', '欢迎下次使用!') self.destroy() login = Login.Win() login.mainloop() def __event_bind(self): self.protocol('WM_DELETE_WINDOW', self.logout) self.tk_tabs_content.tk_tabs_content_0.tk_button_stu_update.bind('<Button-1>', self.updateStudentInfo) self.tk_tabs_content.tk_tabs_content_0.tk_button_stu_reset.bind('<Button-1>', self.stu_reset) self.tk_tabs_content.tk_tabs_content_1.tk_button_analysis.bind('<Button-1>', self.analysisStudentScore) self.tk_tabs_content.tk_tabs_content_1.tk_button_search.bind('<Button-1>', self.searchStudentScore) self.tk_tabs_content.tk_tabs_content_1.tk_button_export.bind('<Button-1>', self.exportStudentScore) self.tk_tabs_content.tk_tabs_content_3.tk_button_update_stu_password.bind('<Button-1>', self.updateStudentPassword) self.tk_button_logout.bind('<Button-1>', self.logout_user)数据库采用mysql 8.0,库名和表如下:
Dao层代码如下:用于访问数据库,向数据库发送sql语句,完成成绩与科目等增删改查任务
Dao.py:
import pymysql def getConnect(): """ 获取数据库连接 :return: """ conn = pymysql.Connect( host='localhost', port=3306, user='#你的数据库用户名', password='#你的数据库密码', db='stu_sc_sys', charset='utf8', cursorclass=pymysql.cursors.DictCursor ) cursor = conn.cursor() return conn, cursor def getUserByIdAndPwd(username, password): conn, cursor = getConnect() sql = f"select uid, uname, ugender, uidentify, uclid, uemail, urole from user where uid='{username}' " \ f"and upwd='{password}'" cursor.execute(sql) res = { "code": 0, "msg": "success", "data": cursor.fetchone() } cursor.close() conn.close() return res def getUserInfoById(uid): conn, cursor = getConnect() sql = f"select uid, uname, ugender, uidentify, uclid, uemail, urole from user where uid='{uid}'" cursor.execute(sql) res = cursor.fetchone() cursor.close() conn.close() return res def updatePassword(uid, origin_pwd, new_pwd): conn, cursor = getConnect() res = { "code": 1, "msg": "修改密码失败!" } if not getUserByIdAndPwd(uid, origin_pwd).get("data"): res = { "code": 1, "msg": "原密码不正确!" } else: sql = f"update user set upwd = '{new_pwd}' where uid = '{uid}'" try: cursor.execute(sql) conn.commit() res = { "code": 0, "msg": "修改成功!" } except Exception as e: conn.rollback() print(e) return res def getScoreByUid(uid, nature='', department='', exam_method=''): """ 通过学号获取成绩 :param uid: :param nature: :param department: :param exam_method: :return: """ conn, cursor = getConnect() sql = f"select ROW_NUMBER() over () as id, uc.cname, c.cnature, c.cdepartment, c.cexammethod, c.ccredit, score " \ f"from user_course uc inner join user u on uc.uid = u.uid inner join course c on uc.cname = c.cname " \ f"where u.uid = '{uid}' and c.cnature like '%{nature}%' and " \ f"c.cdepartment like '%{department}%' and c.cexammethod like '%{exam_method}%'" print(sql) cursor.execute(sql) res = { "code": 0, "msg": "success", "data": cursor.fetchall() } cursor.close() conn.close() return res def getAllUsers(): connection, cursor = getConnect() sql = 'select uid, uname, ugender, uidentify, uclid, uemail, upwd, urole from user' cursor.execute(sql) res = { "code": 0, "msg": "success", "data": cursor.fetchall() } cursor.close() connection.close() return res def getAllStudents(): connection, cursor = getConnect() sql = "select row_number() over () as id, uid, uname, ugender, uidentify, uclid, uemail from user where urole = 1" cursor.execute(sql) res = { "code": 0, "msg": "success", "data": cursor.fetchall() } cursor.close() connection.close() return res def searchStudents(uname, ugender): """ 学生信息搜索 :param uname: :param ugender: :return: """ connection, cursor = getConnect() sql = f"select row_number() over () as id, uid, uname, ugender, uidentify, uclid, uemail, upwd, urole from user " \ f"where urole = 1 and uname like '%{uname}%' and ugender like '%{ugender}%'" cursor.execute(sql) res = { "code": 0, "msg": "success", "data": cursor.fetchall() } cursor.close() connection.close() return res def addStudent(uid, uname, ugender, uidentify, uclid, uemail): """ 添加一个学生信息,密码默认为123456 :param uid: :param uname: :param ugender: :param uidentify: :param uclid: :param uemail: :return: """ connection, cursor = getConnect() sql = f"insert into user(uid, uname, ugender, uidentify, uclid, uemail, upwd) values ('{uid}', '{uname}'" \ f", '{ugender}', '{uidentify}', '{uclid}', '{uemail}', '123456') " res = { "code": 0, "msg": "添加成功!" } try: cursor.execute(sql) connection.commit() except Exception as e: res = { "code": 1, "msg": "添加失败!" } connection.rollback() print(e) cursor.close() connection.close() return res def deleteUser(uid): """ 通过uid删除用户 :param uid: :return: """ connection, cursor = getConnect() sql = f"delete from user where uid = '{uid}'" res = { "code": 0, "msg": "删除成功!" } try: cursor.execute(sql) connection.commit() except Exception as e: res = { "code": 1, "msg": "删除失败!" } connection.rollback() print(e) cursor.close() connection.close() return res def updateUser(uid, uname, ugender, uidentify, uclid, uemail): """ 通过uid更新用户信息 :param uid: :param uname: :param ugender: :param uidentify: :param uclid: :param uemail: :return: """ connection, cursor = getConnect() sql = f"update user set uname = '{uname}', ugender = '{ugender}', uidentify = '{uidentify}', uclid = '{uclid}'" \ f", uemail ='{uemail}' where uid = '{uid}'" print(sql) res = { "code": 0, "msg": "修改成功!" } try: cursor.execute(sql) connection.commit() except Exception as e: res = { "code": 1, "msg": "修改失败!" } connection.rollback() print(e) cursor.close() connection.close() return res def getAllCourses(): """ 获取所有的课程信息 :return: """ connection, cursor = getConnect() sql = "select cid, cname, ccredit, cnature, cdepartment, cexammethod from course" cursor.execute(sql) res = { "code": 0, "msg": "success", "data": cursor.fetchall() } cursor.close() connection.close() return res def getCourseByCid(cid): """ 获取cid的课程 :return: """ connection, cursor = getConnect() sql = f"select cid, cname, cnature, ccredit, cdepartment, cexammethod from course where cid = '{cid}'" cursor.execute(sql) res = { "code": 0, "msg": "success", "data": cursor.fetchall() } cursor.close() connection.close() return res def getDataDictByType(dtype): """ 获取dtype类型的数据字典 :param: :return: """ connection, cursor = getConnect() sql = f"select d.ddtkey as k, d.ddtvalue as v from dictionary d where d.ddtype = '{dtype}'" cursor.execute(sql) res = { "code": 0, "msg": "success", "data": cursor.fetchall() } cursor.close() connection.close() return res def getAllDepartments(): """ 获取所有的学院 :return: """ connection, cursor = getConnect() sql = "select did as k, dname as v from department" cursor.execute(sql) res = { "code": 0, "msg": "success", "data": cursor.fetchall() } cursor.close() connection.close() return res def getMaxStuNumber(s_num_prefix): """ 获取以s_num_prefix开头的最大学号 :return: """ connection, cursor = getConnect() sql = f"select MAX(uid) as max_id from user where uid like '{s_num_prefix}%'" cursor.execute(sql) res = { "code": 0, "msg": "success", "data": cursor.fetchall() } cursor.close() connection.close() return res def addCourse(cname, nature, credit, department, exam_method): """ 添加课程 :return: """ connection, cursor = getConnect() sql = f"insert into course(cname, cnature, ccredit, cdepartment, cexammethod) VALUES ('{cname}', '{nature}'" \ f", '{credit}', '{department}', '{exam_method}')" res = { "code": 0, "msg": "添加课程成功!" } try: cursor.execute(sql) connection.commit() except Exception as e: res = { "code": 1, "msg": "添加课程失败!" } connection.rollback() print(e) cursor.close() connection.close() return res def deleteCourse(cid): """ 删除课程 :return: """ connection, cursor = getConnect() sql = f"delete from course where cid = {cid}" res = { "code": 0, "msg": "删除课程成功!" } try: cursor.execute(sql) connection.commit() except Exception as e: res = { "code": 1, "msg": "删除课程失败!" } connection.rollback() print(e) cursor.close() connection.close() return res def searchCourses(department, exammethod): """ 搜索课程信息 :param department: :param exammethod: :return: """ connection, cursor = getConnect() sql = f"select cid, cname, ccredit, cnature, cdepartment, cexammethod from course " \ f"where cdepartment like '%{department}%' and cexammethod like '%{exammethod}%'" cursor.execute(sql) res = { "code": 0, "msg": "success", "data": cursor.fetchall() } cursor.close() connection.close() return res def updateCourseInfo(cid, cname, nature, credit, department, exammethod): """ 修改课程信息 :param cid: :param cname: :param nature: :param credit: :param department: :param exammethod: :return: """ connection, cursor = getConnect() sql = f"update course set cname = '{cname}', cnature = '{nature}', ccredit = '{credit}'" \ f", cdepartment = '{department}', cexammethod = '{exammethod}' where cid = '{cid}'" res = { "code": 0, "msg": "修改课程成功!" } try: cursor.execute(sql) connection.commit() except Exception as e: res = { "code": 1, "msg": "更新课程失败!" } connection.rollback() print(e) cursor.close() connection.close() return res def getScoreBandByCName(course_name): """ 获取课程名为course_name的各个分段的学生人数 :param course_name: :return: """ connection, cursor = getConnect() sql = f"select SUM(IF(score <= 100 and score >= 90, 1, 0)) as A, SUM(IF(score < 90 and score >= 80, 1, 0)) as B, " \ f"SUM(IF(score < 80 and score >= 70, 1, 0)) as C, SUM(IF(score < 70 and score >= 60, 1, 0)) as D, " \ f"SUM(IF(score < 60, 1, 0)) as E from user_course where cname = '{course_name}'" cursor.execute(sql) res = { "code": 0, "msg": "success", "data": cursor.fetchall() } cursor.close() connection.close() return res def getMaxAndMinAndAvgScoreByCLid(class_id): """ 获取班级号为class_id的班级的各科最高分、最低分以及平均分 :param class_id: :return: """ connection, cursor = getConnect() sql = f"select uc.cname, MAX(score) as max_score, MIN(score) as min_score, AVG(score) as avg_score " \ f"from user_course uc inner join user u on uc.uid = u.uid where u.uclid = '{class_id}' group by uc.cname" cursor.execute(sql) res = { "code": 0, "msg": "success", "data": cursor.fetchall() } cursor.close() connection.close() return res def getOverallGradeLevelByCLid(class_id): """ 获取班级号为class_id的班级综合成绩等级各分段人数 :param class_id: :return: """ connection, cursor = getConnect() sql = f"select SUM(IF(avg_score >= 85 and avg_score <= 100, 1, 0)) as A, " \ f"SUM(IF(avg_score >= 70 and avg_score < 85, 1, 0)) as B, " \ f"SUM(IF(avg_score >= 60 and avg_score < 70, 1, 0)) as C, " \ f"SUM(IF(avg_score < 60, 1, 0)) as D from (" \ f"select AVG(score) as avg_score from user_course uc " \ f"inner join user u on uc.uid = u.uid where u.uclid = '{class_id}' group by u.uid" \ f") s" cursor.execute(sql) res = { "code": 0, "msg": "success", "data": cursor.fetchall() } cursor.close() connection.close() return res def getAllClasses(): """ 获取用户表中已存在的班级号 :return: """ connection, cursor = getConnect() sql = f"select distinct uclid from user where urole = 1" cursor.execute(sql) res = { "code": 0, "msg": "success", "data": cursor.fetchall() } cursor.close() connection.close() return res def getAllCourseAvgScore(uid): """ 获取所有课程的平均分 :return: """ connection, cursor = getConnect() sql = f"select cname, AVG(score) as avg_score from user_course where cname in " \ f"(select cname from user_course where uid = '{uid}') group by cname" cursor.execute(sql) res = { "code": 0, "msg": "success", "data": cursor.fetchall() } cursor.close() connection.close() return res def searchStudentScore(course_name='', course_nature='', course_department=''): """ 搜索学生成绩 :param course_name: :param course_nature: :param course_department: :return: """ connection, cursor = getConnect() sql = f"select ROW_NUMBER() over () as id, u.uid, u.uname, uc.cname, c.cnature, c.cdepartment, c.cexammethod, " \ f"c.ccredit, score from user_course uc inner join user u on uc.uid = u.uid inner join course c " \ f"on uc.cname = c.cname where c.cname like '%{course_name}%' and " \ f"c.cnature like '%{course_nature}%' and c.cdepartment like '%{course_department}%'" cursor.execute(sql) res = { "code": 0, "msg": "success", "data": cursor.fetchall() } cursor.close() connection.close() return res def getScoreByUidAndCName(uid, course_name): """ 查找学号为uid课程为course_name的学生成绩 :param uid: :param course_name: :return: """ connection, cursor = getConnect() sql = f"select uid, cname, score from user_course where uid = '{uid}' and cname = '{course_name}'" cursor.execute(sql) res = { "code": 0, "msg": "success", "data": cursor.fetchall() } cursor.close() connection.close() return res def addStudentScore(uid, course_name, score): connection, cursor = getConnect() if not cursor.execute(f"select uid from user where uid = '{uid}'"): return { "code": 1, "msg": "学号不存在!" } if cursor.execute(f"select 1 from user_course where uid = '{uid}' and cname = '{course_name}' limit 1"): return { "code": 1, "msg": f"该学生的{course_name}课程成绩已经存在!" } sql = f"insert into user_course(uid, cname, score) VALUES ('{uid}', '{course_name}', '{score}')" res = { "code": 0, "msg": "添加成绩成功!" } try: cursor.execute(sql) connection.commit() except Exception as e: res = { "code": 1, "msg": "添加成绩失败!" } connection.rollback() print(e) cursor.close() connection.close() return res def deleteStudentScore(uid, course_name): connection, cursor = getConnect() if not cursor.execute(f"select uid from user where uid = '{uid}'"): return { "code": 1, "msg": "学号不存在!" } sql = f"delete from user_course where uid = '{uid}' and cname = '{course_name}'" res = { "code": 0, "msg": "删除成绩成功!" } try: code = cursor.execute(sql) connection.commit() if code == 0: res = { "code": 0, "msg": f"该学生的{course_name}课程成绩不存在!" } except Exception as e: res = { "code": 1, "msg": "删除成绩失败!" } connection.rollback() print(e) cursor.close() connection.close() return res def updateStudentScore(uid, course_name, score): connection, cursor = getConnect() sql = f"update user_course set score = '{score}' where uid = '{uid}' and cname = '{course_name}'" res = { "code": 0, "msg": "修改成绩成功!" } try: cursor.execute(sql) connection.commit() except Exception as e: res = { "code": 1, "msg": "修改成绩失败!" } connection.rollback() print(e) cursor.close() connection.close() return res
from tkinter import *from tkinter import messagebox, filedialogfrom tkinter.ttk import *
import openpyxl as openpyxl
import AddCoursePageimport AddScorePageimport ClassGradeAnalysisimport ComprehensivePerformanceEvaluationimport CourseScoreAnalysisimport Daoimport DeleteCoursePageimport DeleteScorePageimport Loginimport UpdateCoursePage
import AddStudentPageimport DeleteStudentPageimport UpdateScorePageimport UpdateStudentPage
import numpy as npimport matplotlib.pyplot as plt
class WinGUI(Tk): def __init__(self): super().__init__() self.__win() self.tk_label_title = self.__tk_label_title() self.tk_label_current_user = self.__tk_label_current_user() self.tk_tabs_content = Frame_content(self) self.tk_button_logout_user = self.__tk_button_logout_user()
def __win(self): self.title("教师端") # 设置窗口大小、居中 width = 1000 height = 600 screenwidth = self.winfo_screenwidth() screenheight = self.winfo_screenheight() geometry = '%dx%d+%d+%d' % (width, height, (screenwidth - width) / 2, (screenheight - height) / 2) self.geometry(geometry) self.resizable(width=False, height=False) self.iconbitmap('logo.ico')
def __tk_label_title(self): label = Label(self, text="学生成绩管理系统", anchor="center") label.place(x=0, y=0, width=800, height=100) return label
def __tk_label_current_user(self): label = Label(self, text="当前用户:admin", anchor="center") label.place(x=800, y=70, width=150, height=30) return label
def __tk_button_logout_user(self): btn = Button(self, text="退出") btn.place(x=950, y=70, width=50, height=30) return btn
class Frame_content(Notebook): def __init__(self, parent): super().__init__(parent) self.__frame()
def __frame(self): self.tk_tabs_content_0 = Frame_content_0(self) self.add(self.tk_tabs_content_0, text="个人资料")
self.tk_tabs_content_1 = Frame_content_1(self) self.add(self.tk_tabs_content_1, text="学生查询")
self.tk_tabs_content_2 = Frame_content_2(self) self.add(self.tk_tabs_content_2, text="成绩查询")
self.tk_tabs_content_3 = Frame_content_3(self) self.add(self.tk_tabs_content_3, text="成绩分析")
self.tk_tabs_content_4 = Frame_content_4(self) self.add(self.tk_tabs_content_4, text="修改密码")
self.tk_tabs_content_5 = Frame_content_5(self) self.add(self.tk_tabs_content_5, text="课程管理")
self.place(x=0, y=100, width=1000, height=500)
class Frame_content_0(Frame): def __init__(self, parent): super().__init__(parent) self.__frame() self.tk_label_tea_number = self.__tk_label_tea_number() self.tk_input_tea_number = self.__tk_input_tea_number() self.tk_label_tea_name = self.__tk_label_tea_name() self.tk_input_tea_name = self.__tk_input_tea_name() self.tk_label_tea_gender = self.__tk_label_tea_gender() self.tk_select_tea_gender = self.__tk_select_tea_gender() self.tk_label_tea_identity = self.__tk_label_tea_identity() self.tk_input_tea_identity = self.__tk_input_tea_identity() self.tk_label_tea_email = self.__tk_label_tea_email() self.tk_input_tea_email = self.__tk_input_tea_email() self.tk_button_tea_update = self.__tk_button_tea_update() self.tk_button_tea_reset = self.__tk_button_tea_reset()
def __frame(self): self.place(x=0, y=100, width=1000, height=500)
def __tk_label_tea_number(self): label = Label(self, text="工号", anchor="e") label.place(x=360, y=40, width=100, height=30) return label
def __tk_input_tea_number(self): self.tea_number = StringVar(self) ipt = Entry(self, text=self.tea_number) ipt.place(x=490, y=40, width=150, height=30) ipt.config(stat='disable') return ipt
def __tk_label_tea_name(self): label = Label(self, text="姓名", anchor="e") label.place(x=360, y=110, width=100, height=30) return label
def __tk_input_tea_name(self): self.tea_name = StringVar(self) ipt = Entry(self, text=self.tea_name) ipt.place(x=490, y=110, width=150, height=30) return ipt
def __tk_label_tea_gender(self): label = Label(self, text="性别", anchor="e") label.place(x=360, y=180, width=100, height=30) return label
def __tk_select_tea_gender(self): cb = Combobox(self, state='readonly') cb['values'] = ("男", "女") cb.place(x=490, y=180, width=150, height=30) return cb
def __tk_label_tea_identity(self): label = Label(self, text="身份证号", anchor="e") label.place(x=360, y=250, width=100, height=30) return label
def __tk_input_tea_identity(self): self.tea_identify = StringVar(self) ipt = Entry(self, text=self.tea_identify) ipt.place(x=490, y=250, width=150, height=30) return ipt
def __tk_label_tea_email(self): label = Label(self, text="电子邮箱", anchor="e") label.place(x=360, y=320, width=100, height=30) return label
def __tk_input_tea_email(self): self.tea_email = StringVar(self) ipt = Entry(self, text=self.tea_email) ipt.place(x=490, y=320, width=150, height=30) return ipt
def __tk_button_tea_update(self): btn = Button(self, text="修改") btn.place(x=400, y=390, width=80, height=30) return btn
def __tk_button_tea_reset(self): btn = Button(self, text="重置") btn.place(x=520, y=390, width=80, height=30) return btn
class Frame_content_1(Frame): def __init__(self, parent): super().__init__(parent) self.__frame() self.tk_table_student_query = self.__tk_table_student_query() self.tk_input_stu_name = self.__tk_input_stu_name() self.tk_select_box_stu_gender = self.__tk_select_box_stu_gender() self.tk_button_stu_search = self.__tk_button_stu_search() self.tk_button_addStudent = self.__tk_button_addStudent() self.tk_button_delete_student = self.__tk_button_delete_student() self.tk_button_stu_refresh = self.__tk_button_stu_refresh() self.tk_button_studentinfo_export = self.__tk_button_studentinfo_export()
def __frame(self): self.place(x=0, y=100, width=1000, height=500)
def __tk_table_student_query(self): # 表头字段 表头宽度 self.tk_table_student_manage_columns = {"ID": 50, "学号": 100, "姓名": 150, '性别': 100, '身份证号': 300, '班级': 100, '邮箱': 200} # 初始化表格 表格是基于Treeview,tkinter本身没有表格。show="headings" 为隐藏首列。 tk_table = Treeview(self, show="headings", columns=list(self.tk_table_student_manage_columns)) for text, width in self.tk_table_student_manage_columns.items(): # 批量设置列属性 tk_table.heading(text, text=text, anchor='center') tk_table.column(text, anchor='center', width=width, stretch=False) # stretch 不自动拉伸
# 插入数据示例 # # # 导入初始数据 self.tk_student_table_dataset = Dao.getAllStudents() if self.tk_student_table_dataset.get("code") == 0: if self.tk_student_table_dataset.get("data"): print(self.tk_student_table_dataset.get("data")) for values in self.tk_student_table_dataset.get("data"): tk_table.insert('', END, values=list(values.values())) else: print("未查询到数据!") else: print("数据查询异常!")
tk_table.place(x=0, y=60, width=1000, height=415) return tk_table
def __tk_input_stu_name(self): ipt = Entry(self) ipt.place(x=360, y=10, width=150, height=30) return ipt
def __tk_select_box_stu_gender(self): cb = Combobox(self, state="readonly") cb['values'] = ("请选择性别", "男", "女") cb.place(x=540, y=10, width=150, height=30) cb.current(0) return cb
def __tk_button_stu_search(self): btn = Button(self, text="搜索") btn.place(x=720, y=10, width=70, height=30) return btn
def __tk_button_stu_refresh(self): btn = Button(self, text="刷新") btn.place(x=820, y=10, width=70, height=30) return btn
def __tk_button_addStudent(self): btn = Button(self, text="添加学生") btn.place(x=50, y=10, width=100, height=30) return btn
def __tk_button_delete_student(self): btn = Button(self, text="删除学生") btn.place(x=180, y=10, width=100, height=30) return btn
def __tk_button_studentinfo_export(self): btn = Button(self, text="导出") btn.place(x=920, y=10, width=50, height=30) return btn
class Frame_content_2(Frame): def __init__(self, parent): super().__init__(parent) self.__frame() self.tk_table_stu_score = self.__tk_table_stu_score() self.tk_button_add_score = self.__tk_button_add_score() self.tk_button_delete_score = self.__tk_button_delete_score() self.tk_select_box_score_course_name = self.__tk_select_box_score_course_name() self.tk_select_box_score_nature = self.__tk_select_box_score_nature() self.tk_select_box_score_department = self.__tk_select_box_score_department() self.tk_button_stu_score_search = self.__tk_button_stu_score_search() self.tk_button_stu_score_export = self.__tk_button_stu_score_export()
def __frame(self): self.place(x=0, y=100, width=1000, height=500)
def __tk_table_stu_score(self): # 表头字段 表头宽度 self.tk_table_stu_score_columns = {"#": 50, "学号": 70, "姓名": 80, "课程名称": 200, "课程性质": 100, "开课学院": 270, "考试方式": 80, "学分": 50, "成绩": 100} # 初始化表格 表格是基于Treeview,tkinter本身没有表格。show="headings" 为隐藏首列。 tk_table = Treeview(self, show="headings", columns=list(self.tk_table_stu_score_columns)) for text, width in self.tk_table_stu_score_columns.items(): # 批量设置列属性 tk_table.heading(text, text=text, anchor='center') tk_table.column(text, anchor='center', width=width, stretch=False) # stretch 不自动拉伸
# 插入数据示例 self.tk_score_table_dataset = Dao.searchStudentScore() # 导入初始数据 if self.tk_score_table_dataset.get("code") == 0 and self.tk_score_table_dataset.get("data"): for data in self.tk_score_table_dataset.get("data"): tk_table.insert('', END, values=list(data.values()))
tk_table.place(x=0, y=60, width=1000, height=415) return tk_table
def __tk_button_add_score(self): btn = Button(self, text="添加成绩") btn.place(x=50, y=10, width=100, height=30) return btn
def __tk_button_delete_score(self): btn = Button(self, text="删除成绩") btn.place(x=170, y=10, width=100, height=30) return btn
def __tk_select_box_score_course_name(self): cb = Combobox(self, state="readonly") values = ["请选择课程名称"] for i in Dao.getAllCourses().get("data"): values.append(i.get("cname")) cb['values'] = values cb.current(0) cb.place(x=290, y=10, width=150, height=30) return cb
def __tk_select_box_score_nature(self): cb = Combobox(self, state="readonly") values = ["请选择课程性质"] for i in Dao.getDataDictByType("nature").get("data"): values.append(i.get("v")) cb['values'] = values cb.current(0) cb.place(x=460, y=10, width=150, height=30) return cb
def __tk_select_box_score_department(self): cb = Combobox(self, state="readonly") values = ["请选择开课学院"] for i in Dao.getAllDepartments().get("data"): values.append(i.get("v")) cb['values'] = values cb.current(0) cb.place(x=630, y=10, width=150, height=30) return cb
def __tk_button_stu_score_search(self): btn = Button(self, text="搜索") btn.place(x=800, y=10, width=70, height=30) return btn
def __tk_button_stu_score_export(self): btn = Button(self, text="导出") btn.place(x=890, y=10, width=70, height=30) return btn
class Frame_content_3(Frame): def __init__(self, parent): super().__init__(parent) self.__frame() self.tk_button_pieChart = self.__tk_button_pieChart() self.tk_button_columnChart = self.__tk_button_columnChart() self.tk_button_paratacticColumnChart = self.__tk_button_paratacticColumnChart()
def __frame(self): self.place(x=0, y=100, width=1000, height=500)
def __tk_button_columnChart(self): btn = Button(self, text="课程成绩分析") btn.place(x=80, y=50, width=150, height=70) return btn
def __tk_button_paratacticColumnChart(self): btn = Button(self, text="班级成绩分析") btn.place(x=420, y=50, width=150, height=70) return btn
def __tk_button_pieChart(self): btn = Button(self, text="综合成绩评定") btn.place(x=760, y=50, width=150, height=70) return btn
class Frame_content_4(Frame): def __init__(self, parent): super().__init__(parent) self.__frame() self.tk_label_original_pwd = self.__tk_label_original_pwd() self.tk_input_original_pwd = self.__tk_input_original_pwd() self.tk_label_new_pwd = self.__tk_label_new_pwd() self.tk_input_new_pwd = self.__tk_input_new_pwd() self.tk_label_confirm_pwd = self.__tk_label_confirm_pwd() self.tk_input_confirm_pwd = self.__tk_input_confirm_pwd() self.tk_button_update_tea_pwd = self.__tk_button_update_tea_pwd()
def __frame(self): self.place(x=0, y=100, width=1000, height=500)
def __tk_label_original_pwd(self): label = Label(self, text="原密码", anchor="e") label.place(x=360, y=40, width=100, height=30) return label
def __tk_input_original_pwd(self): ipt = Entry(self, show='*') ipt.place(x=490, y=40, width=150, height=30) return ipt
def __tk_label_new_pwd(self): label = Label(self, text="新密码", anchor="e") label.place(x=360, y=110, width=100, height=30) return label
def __tk_input_new_pwd(self): ipt = Entry(self, show='*') ipt.place(x=490, y=110, width=150, height=30) return ipt
def __tk_label_confirm_pwd(self): label = Label(self, text="确认密码", anchor="e") label.place(x=360, y=180, width=100, height=30) return label
def __tk_input_confirm_pwd(self): ipt = Entry(self, show='*') ipt.place(x=490, y=180, width=150, height=30) return ipt
def __tk_button_update_tea_pwd(self): btn = Button(self, text="修改") btn.place(x=450, y=260, width=100, height=30) return btn
class Frame_content_5(Frame): def __init__(self, parent): super().__init__(parent) self.__frame() self.tk_table_course_manage = self.__tk_table_course_manage() self.tk_button_add_course = self.__tk_button_add_course() self.tk_button_delete_course = self.__tk_button_delete_course() self.tk_select_box_course_department = self.__tk_select_box_course_department() self.tk_select_box_course_exam_method = self.__tk_select_box_course_exam_method() self.tk_button_course_search = self.__tk_button_course_search() self.tk_button_course_export = self.__tk_button_course_export()
def __frame(self): self.place(x=0, y=100, width=1000, height=500)
def __tk_table_course_manage(self): # 表头字段 表头宽度 self.tk_table_course_manage_columns = {"课程号": 100, "课程名称": 200, "学分": 100, "课程性质": 200, "开课学院": 300, "考试方式": 100} # 初始化表格 表格是基于Treeview,tkinter本身没有表格。show="headings" 为隐藏首列。 tk_table = Treeview(self, show="headings", columns=list(self.tk_table_course_manage_columns)) for text, width in self.tk_table_course_manage_columns.items(): # 批量设置列属性 tk_table.heading(text, text=text, anchor='center') tk_table.column(text, anchor='center', width=width, stretch=False) # stretch 不自动拉伸
# 插入数据示例 self.tk_course_table_dataset = Dao.getAllCourses() # 导入初始数据 if self.tk_course_table_dataset.get("code") == 0 and self.tk_course_table_dataset.get("data"): for data in self.tk_course_table_dataset.get("data"): tk_table.insert('', END, values=list(data.values()))
tk_table.place(x=0, y=60, width=1000, height=415) return tk_table
def __tk_button_add_course(self): btn = Button(self, text="添加课程") btn.place(x=50, y=10, width=100, height=30) return btn
def __tk_button_delete_course(self): btn = Button(self, text="删除课程") btn.place(x=180, y=10, width=100, height=30) return btn
def __tk_select_box_course_department(self): cb = Combobox(self, state="readonly") values = ["请选择开课学院"] for i in Dao.getAllDepartments().get("data"): values.append(i.get("v")) cb['values'] = values cb.current(0) cb.place(x=310, y=10, width=150, height=30) return cb
def __tk_select_box_course_exam_method(self): cb = Combobox(self, state="readonly") values = ["请选择考试方式"] for i in Dao.getDataDictByType("exammethod").get("data"): values.append(i.get("v")) cb['values'] = values cb.current(0) cb.place(x=490, y=10, width=150, height=30) return cb
def __tk_button_course_search(self): btn = Button(self, text="搜索") btn.place(x=670, y=10, width=100, height=30) return btn
def __tk_button_course_export(self): btn = Button(self, text="导出") btn.place(x=800, y=10, width=100, height=30) return btn
class Win(WinGUI): def __init__(self, current_user): super().__init__() self.__event_bind() self.current_user = current_user self.uid = current_user.get("uid") self.tk_label_current_user['text'] = "当前用户:" + current_user.get("uname") self.tk_tabs_content.tk_tabs_content_0.tea_number.set(current_user.get("uid")) self.tk_tabs_content.tk_tabs_content_0.tea_name.set(current_user.get("uname")) self.tk_tabs_content.tk_tabs_content_0.tk_select_tea_gender.current(0 if current_user.get("ugender") == '男' else 1) self.tk_tabs_content.tk_tabs_content_0.tea_identify.set(current_user.get("uidentify")) self.tk_tabs_content.tk_tabs_content_0.tea_email.set(current_user.get("uemail"))
def logout(self): try: self.updateStudent.destroy() self.addInfo.destroy() self.delete.destroy() except Exception as e: print(e) messagebox.showwarning('提示', '欢迎下次使用!') self.destroy() login = Login.Win() login.mainloop()
def updateStudentInfo(self, evt): current_focus = self.tk_tabs_content.tk_tabs_content_1.tk_table_student_query.focus() current_studentinfo = self.tk_tabs_content.tk_tabs_content_1.tk_table_student_query.set(current_focus) current_uid = current_studentinfo.get('学号') self.updateStudent = UpdateStudentPage.Win(current_uid) self.updateStudent.mainloop() print("<<TreeviewSelect>>事件未处理", evt)
def updateTeacherInfo(self, evt): __tea_name = self.tk_tabs_content.tk_tabs_content_0.tk_input_tea_name.get() __tea_gender = self.tk_tabs_content.tk_tabs_content_0.tk_select_tea_gender.get() __tea_identify = self.tk_tabs_content.tk_tabs_content_0.tk_input_tea_identity.get() __tea_email = self.tk_tabs_content.tk_tabs_content_0.tk_input_tea_email.get() if not __tea_name or not __tea_gender or not __tea_identify or not __tea_email: messagebox.showinfo("提示", "必填项不能为空!") return if not re.match(r'^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$', __tea_identify): messagebox.showinfo("提示", "身份证格式不合法!") return if not re.match(r'^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$', __tea_email): messagebox.showinfo("提示", "电子邮箱格式不合法!") return res = Dao.updateUser(self.uid, __tea_name, __tea_gender, __tea_identify, 0, __tea_email) messagebox.showinfo("提示", res.get("msg")) self.tk_label_current_user['text'] = "当前用户:" + __tea_name print("更新教师信息", evt)
def resetTeacherInfo(self, evt): self.tk_tabs_content.tk_tabs_content_0.tea_name.set(self.current_user.get("uname")) self.tk_tabs_content.tk_tabs_content_0.tk_select_tea_gender.current(0 if self.current_user.get("ugender") == '男' else 1) self.tk_tabs_content.tk_tabs_content_0.tea_identify.set(self.current_user.get("uidentify")) self.tk_tabs_content.tk_tabs_content_0.tea_email.set(self.current_user.get("uemail")) print("重置教师信息", evt)
def searchStudentInfo(self, evt): for _ in map(self.tk_tabs_content.tk_tabs_content_1.tk_table_student_query.delete, self.tk_tabs_content.tk_tabs_content_1.tk_table_student_query.get_children("")): pass value = self.tk_tabs_content.tk_tabs_content_1.tk_input_stu_name.get() num = self.tk_tabs_content.tk_tabs_content_1.tk_select_box_stu_gender.get() print(num, value) if num == '请选择性别': result = Dao.searchStudents(value, '') else: result = Dao.searchStudents(value, num) if result.get("code") == 0: if result.get("data"): # print(result.get("data")) for values in result.get("data"): self.tk_tabs_content.tk_tabs_content_1.tk_table_student_query.insert('', END, values=list(values.values())) else: print("未查询到数据!") else: print("数据查询异常!") print("搜索学生信息", evt)
def updateStudentScore(self, evt): current_item = self.tk_tabs_content.tk_tabs_content_2.tk_table_stu_score.set(self.tk_tabs_content.tk_tabs_content_2.tk_table_stu_score.focus()) data = { "uid": current_item.get("学号"), "cname": current_item.get("课程名称"), "score": current_item.get("成绩") } updateScorePage = UpdateScorePage.Win(data) updateScorePage.mainloop() print("修改学生课程成绩", evt)
def searchStuScore(self, evt): __score_manage = self.tk_tabs_content.tk_tabs_content_2 __course_name = __score_manage.tk_select_box_score_course_name.get() __course_nature = __score_manage.tk_select_box_score_nature.get() __course_department = __score_manage.tk_select_box_score_department.get() if __score_manage.tk_select_box_score_course_name.current() == 0: __course_name = '' if __score_manage.tk_select_box_score_nature.current() == 0: __course_nature = '' if __score_manage.tk_select_box_score_department.current() == 0: __course_department = '' for _ in map(__score_manage.tk_table_stu_score.delete, __score_manage.tk_table_stu_score.get_children("")): pass __score_manage.tk_score_table_dataset = Dao.searchStudentScore(__course_name, __course_nature, __course_department) # 导入初始数据 if __score_manage.tk_score_table_dataset.get("code") == 0 and __score_manage.tk_score_table_dataset.get("data"): for data in __score_manage.tk_score_table_dataset.get("data"): __score_manage.tk_table_stu_score.insert('', END, values=list(data.values())) __score_manage.tk_select_box_score_course_name.current(0) __score_manage.tk_select_box_score_nature.current(0) __score_manage.tk_select_box_score_department.current(0) print("搜索学生成绩!")
def exportStuScore(self, evt): path = filedialog.askdirectory() try: book = openpyxl.Workbook() sheet = book.active fff = list(self.tk_tabs_content.tk_tabs_content_2.tk_table_stu_score_columns.keys()) # 获取表头信息 sheet.append(fff) dataset = [list(data_item.values()) for data_item in self.tk_tabs_content.tk_tabs_content_2.tk_score_table_dataset.get("data")] print(dataset) for i in dataset: sheet.append(i) book.save(f"{path}/student_score.xlsx") messagebox.showinfo("提示", "导出成功!") except Exception as e: messagebox.showinfo("提示", "导出失败!") print(e) print("导出学生成绩!", evt)
def addStudentInfo(self, evt): self.addInfo = AddStudentPage.Win() self.addInfo.mainloop() print("<Button-1>事件未处理", evt)
def deleteStudentInfo(self, evt): self.delete = DeleteStudentPage.Win() self.delete.mainloop() print("<Button-1>事件未处理", evt)
def addStudentScore(self, evt): addScorePage = AddScorePage.Win() addScorePage.mainloop()
def deleteStudentScore(self, evt): deleteScorePage = DeleteScorePage.Win() deleteScorePage.mainloop() print("删除学生成绩", evt)
def updateTeacherPassword(self, evt): __original_pwd = self.tk_tabs_content.tk_tabs_content_4.tk_input_original_pwd.get() __new_pwd = self.tk_tabs_content.tk_tabs_content_4.tk_input_new_pwd.get() __confirm_pwd = self.tk_tabs_content.tk_tabs_content_4.tk_input_confirm_pwd.get() if __original_pwd == '' or __new_pwd == '' or __confirm_pwd == '': messagebox.showwarning("提示", "必填项未填写!") return if not re.match(r"^[0-9a-zA-Z~!@#$%^&*._?]{6,18}$", __original_pwd) \ or not re.match(r"^[0-9a-zA-Z~!@#$%^&*._?]{6,18}$", __new_pwd) \ or not re.match(r"^[0-9a-zA-Z~!@#$%^&*._?]{6,18}$", __confirm_pwd): messagebox.showwarning("提示", "密码格式应为6-18位数字、字母、特殊字符的组合!") return if __new_pwd != __confirm_pwd: messagebox.showwarning("提示", "两次密码输入不一致") return res = Dao.updatePassword(self.uid, __original_pwd, __new_pwd) messagebox.showinfo("提示", res.get("msg")) if res.get("code") == 0: self.destroy() login = Login.Win() login.mainloop() print("修改教师密码", evt)
def addCourseInfo(self, evt): addCoursePage = AddCoursePage.Win() addCoursePage.mainloop() print("添加成绩!")
def deleteCourseInfo(self, evt): deleteCoursePage = DeleteCoursePage.Win() deleteCoursePage.mainloop() print("删除课程!")
def searchCourseInfo(self, evt): __course_manage = self.tk_tabs_content.tk_tabs_content_5 __department = __course_manage.tk_select_box_course_department.get() __exammethod = __course_manage.tk_select_box_course_exam_method.get() if __course_manage.tk_select_box_course_department.current() == 0: __department = '' if __course_manage.tk_select_box_course_exam_method.current() == 0: __exammethod = '' for _ in map(__course_manage.tk_table_course_manage.delete, __course_manage.tk_table_course_manage.get_children("")): pass self.tk_tabs_content.tk_tabs_content_5.tk_course_table_dataset = Dao.searchCourses(__department, __exammethod) # 导入初始数据 if self.tk_tabs_content.tk_tabs_content_5.tk_course_table_dataset.get("code") == 0 and self.tk_tabs_content.tk_tabs_content_5.tk_course_table_dataset.get("data"): for data in self.tk_tabs_content.tk_tabs_content_5.tk_course_table_dataset.get("data"): __course_manage.tk_table_course_manage.insert('', END, values=list(data.values())) __course_manage.tk_select_box_course_department.current(0) __course_manage.tk_select_box_course_exam_method.current(0) print("查询课程!")
def updateCourseInfo(self, evt): __focus = self.tk_tabs_content.tk_tabs_content_5.tk_table_course_manage.focus() current_item = self.tk_tabs_content.tk_tabs_content_5.tk_table_course_manage.set(__focus) __cid = current_item.get("课程号") self.updateCoursePage = UpdateCoursePage.Win(__cid) self.updateCoursePage.mainloop() print("更新课程信息!")
def exportCourseInfo(self, evt): path = filedialog.askdirectory() try: book = openpyxl.Workbook() sheet = book.active fff = list(self.tk_tabs_content.tk_tabs_content_5.tk_table_course_manage_columns.keys()) # 获取表头信息 sheet.append(fff) dataset = [list(data_item.values()) for data_item in self.tk_tabs_content.tk_tabs_content_5.tk_course_table_dataset.get("data")] print(dataset) for i in dataset: sheet.append(i) book.save(path + "/course_info.xlsx") messagebox.showinfo("提示", "导出成功!") except Exception as e: messagebox.showinfo("提示", "导出失败!") print(e)
def logout_user(self, evt): messagebox.showwarning('提示', '欢迎下次使用!') self.destroy() login = Login.Win() login.mainloop()
def studentinfo_refresh(self, evt): # 删除原结点,加入新结点 for _ in map(self.tk_tabs_content.tk_tabs_content_1.tk_table_student_query.delete, self.tk_tabs_content.tk_tabs_content_1.tk_table_student_query.get_children("")): pass result = Dao.getAllStudents() if result.get("code") == 0: if result.get("data"): # print(result.get("data")) for values in result.get("data"): self.tk_tabs_content.tk_tabs_content_1.tk_table_student_query.insert('', END, values=list(values.values())) else: print("未查询到数据!") else: print("数据查询异常!")
def studentinfo_export(self, evt): path = filedialog.askdirectory() try: book = openpyxl.Workbook() sheet = book.active fff = list(self.tk_tabs_content.tk_tabs_content_1.tk_table_student_manage_columns.keys()) # 获取表头信息 sheet.append(fff) dataset = [list(data_item.values()) for data_item in self.tk_tabs_content.tk_tabs_content_1.tk_student_table_dataset.get("data")] print(dataset) for i in dataset: sheet.append(i) book.save(path + "/student_info.xlsx") messagebox.showinfo("提示", "导出成功!") except Exception as e: messagebox.showinfo("提示", "导出失败!") print(e)
def columnChart(self, evt): courseScoreAnalysis = CourseScoreAnalysis.Win() courseScoreAnalysis.mainloop()
def paratacticColumnChart(self, evt): classGradeAnalysis = ClassGradeAnalysis.Win() classGradeAnalysis.mainloop()
def pieChart(self, evt): comprehensivePerformanceEvaluation = ComprehensivePerformanceEvaluation.Win() comprehensivePerformanceEvaluation.mainloop()
def __event_bind(self): self.protocol('WM_DELETE_WINDOW', self.logout) self.tk_tabs_content.tk_tabs_content_1.tk_table_student_query.bind('<<TreeviewSelect>>', self.updateStudentInfo) self.tk_tabs_content.tk_tabs_content_0.tk_button_tea_update.bind('<Button-1>', self.updateTeacherInfo) self.tk_tabs_content.tk_tabs_content_0.tk_button_tea_reset.bind('<Button-1>', self.resetTeacherInfo) self.tk_tabs_content.tk_tabs_content_1.tk_button_stu_search.bind('<Button-1>', self.searchStudentInfo) self.tk_tabs_content.tk_tabs_content_1.tk_button_addStudent.bind('<Button-1>', self.addStudentInfo) self.tk_tabs_content.tk_tabs_content_1.tk_button_delete_student.bind('<Button-1>', self.deleteStudentInfo) self.tk_tabs_content.tk_tabs_content_1.tk_button_stu_refresh.bind('<Button-1>', self.studentinfo_refresh) self.tk_tabs_content.tk_tabs_content_1.tk_button_studentinfo_export.bind('<Button-1>', self.studentinfo_export) self.tk_tabs_content.tk_tabs_content_2.tk_button_add_score.bind('<Button-1>', self.addStudentScore) self.tk_tabs_content.tk_tabs_content_2.tk_button_delete_score.bind('<Button-1>', self.deleteStudentScore) self.tk_tabs_content.tk_tabs_content_2.tk_table_stu_score.bind('<<TreeviewSelect>>', self.updateStudentScore) self.tk_tabs_content.tk_tabs_content_2.tk_button_stu_score_search.bind('<Button-1>', self.searchStuScore) self.tk_tabs_content.tk_tabs_content_2.tk_button_stu_score_export.bind('<Button-1>', self.exportStuScore) self.tk_tabs_content.tk_tabs_content_3.tk_button_columnChart.bind('<Button-1>', self.columnChart) self.tk_tabs_content.tk_tabs_content_3.tk_button_paratacticColumnChart.bind('<Button-1>', self.paratacticColumnChart) self.tk_tabs_content.tk_tabs_content_3.tk_button_pieChart.bind('<Button-1>', self.pieChart)
self.tk_tabs_content.tk_tabs_content_4.tk_button_update_tea_pwd.bind('<Button-1>', self.updateTeacherPassword) self.tk_tabs_content.tk_tabs_content_5.tk_button_add_course.bind('<Button-1>', self.addCourseInfo) self.tk_tabs_content.tk_tabs_content_5.tk_button_delete_course.bind('<Button-1>', self.deleteCourseInfo) self.tk_tabs_content.tk_tabs_content_5.tk_button_course_search.bind('<Button-1>', self.searchCourseInfo) self.tk_tabs_content.tk_tabs_content_5.tk_button_course_export.bind('<Button-1>', self.exportCourseInfo) self.tk_tabs_content.tk_tabs_content_5.tk_table_course_manage.bind('<<TreeviewSelect>>', self.updateCourseInfo) self.tk_button_logout_user.bind('<Button-1>', self.logout_user) 标签:__,课程设计,tkinter,Python,self,content,tabs,tk,def From: https://www.cnblogs.com/sqwu666/p/17504464.html