数据库实战:基于Tkinter+MySQL的学生成绩管理系统
作者:mmseoamin日期:2023-12-27

学生成绩管理系统

文章目录

  • 前言
  • 实验环境
  • MySQL部分
    • 1. 导入信息
    • 2. 演示说明
    • Python程序设计部分
      • 1. 连接数据库
      • 2. 登录界面
      • 3. 注册界面
      • 4. 主界面
      • 5. 查询信息
      • 6. 修改密码
      • 7. 成绩分析
        • 7.1 通过学号查询成绩
        • 7.2 通过课程号查询成绩
        • 7. 主函数
        • 尾声

          前言

          用Python和数据库一起实现了一个简单的学生成绩管理系统,一起来看看吧!

          本篇博客主要分为两大部分,数据库部分和Python程序设计部分,先将数据导入到数据库中,随后通过python程序设计连接到数据库,实现一系列的操作。

          实验环境

          python + tkinter + mysql

          MySQL部分

          1. 导入信息

          以下是用MySQL语言创建用户表,学生表,课程表以及成绩表的完整程序,直接导入数据库即可。

          -- ----------------------------
          -- Table structure for `users`
          -- ----------------------------
          CREATE TABLE `users` (
            `username` varchar(20),
            `passwords` varchar(20),
            PRIMARY KEY(username)
          )ENGINE=InnoDB DEFAULT CHARSET=utf8;
          -- ----------------------------
          -- Records of users
          -- ----------------------------
          INSERT INTO users VALUES ('user01', '123');
          -- ----------------------------
          -- Table structure for `student`
          -- ----------------------------
          CREATE TABLE `student` (
            `sno` char(7) NOT NULL,
            `sname` char(10) NOT NULL,
            `ssex` enum('男','女') DEFAULT '男',
            `sage` tinyint(3) unsigned DEFAULT NULL,
            `sdept` char(20) DEFAULT '计算机科学与工程学院',
            PRIMARY KEY (`sno`)
          ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
          -- ----------------------------
          -- Records of student
          -- ----------------------------
          INSERT INTO student VALUES ('9512101', '李勇', '男', '19', '计算机系');
          INSERT INTO student VALUES ('9512103', '王敏', '女', '20', '计算机系');
          INSERT INTO student VALUES ('9513101', '周璐', '女', '17', '物理系');
          INSERT INTO student VALUES ('9521101', '张莉', '女', '22', '计算机系');
          INSERT INTO student VALUES ('9521102', '吴宾', '男', '21', '计算机系');
          INSERT INTO student VALUES ('9521103', '张海', '男', '20', '计算机系');
          INSERT INTO student VALUES ('9531101', '钱小平', '女', '18', '数学系');
          INSERT INTO student VALUES ('9531102', '王大力', '男', '19', '数学系');
          INSERT INTO student VALUES ('9531103', '刘梅', '女', '19', '计算机系');
          -- ----------------------------
          -- Table structure for `course`
          -- ----------------------------
          CREATE TABLE `course` (
            `cno` char(4) NOT NULL,
            `cname` varchar(40) NOT NULL,
            `cpno` char(4) DEFAULT NULL,
            `ccredit` tinyint(4) DEFAULT NULL,
            PRIMARY KEY (`cno`),
            KEY `cpno` (`cpno`),
            CONSTRAINT `course_ibfk_1` FOREIGN KEY (`cpno`) REFERENCES `course` (`cno`)
          ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
          -- ----------------------------
          -- Records of course
          -- ----------------------------
          INSERT INTO course VALUES ('C001', '计算机导论', null, '3');
          INSERT INTO course VALUES ('C002', '高等数学', null, '4');
          INSERT INTO course VALUES ('C003', '程序设计语言', 'C001', '4');
          INSERT INTO course VALUES ('C004', '数据结构与算法', 'C003', '5');
          INSERT INTO course VALUES ('C005', '数据库原理与应用', 'C004', '4');
          -- ----------------------------
          -- Table structure for `sc`
          -- ----------------------------
          CREATE TABLE `sc` (
            `sno` char(7) NOT NULL DEFAULT '',
            `cno` char(4) NOT NULL DEFAULT '',
            `grade` decimal(5,1) DEFAULT NULL,
            PRIMARY KEY (`sno`,`cno`),
            KEY `sno`(`sno`),
            KEY `cno` (`cno`),
            CONSTRAINT `sc_ibfk_1` FOREIGN KEY (`sno`) REFERENCES `student` (`sno`),
            CONSTRAINT `sc_ibfk_2` FOREIGN KEY (`cno`) REFERENCES `course` (`cno`)
          ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
          -- ----------------------------
          -- Records of sc
          -- ----------------------------
          INSERT INTO sc VALUES ('9512101', 'C001', null);
          INSERT INTO sc VALUES ('9512101', 'C002', '87.0');
          INSERT INTO sc VALUES ('9512101', 'C003', '95.0');
          INSERT INTO sc VALUES ('9512101', 'C004', '76.0');
          INSERT INTO sc VALUES ('9512101', 'C005', '80.0');
          INSERT INTO sc VALUES ('9512103', 'C003', '51.0');
          INSERT INTO sc VALUES ('9512103', 'C005', '60.0');
          INSERT INTO sc VALUES ('9521101', 'C005', '72.0');
          INSERT INTO sc VALUES ('9521102', 'C005', '80.0');
          INSERT INTO sc VALUES ('9521103', 'C005', '45.0');
          INSERT INTO sc VALUES ('9531101', 'C005', '81.0');
          INSERT INTO sc VALUES ('9531101', 'C001', null);
          INSERT INTO sc VALUES ('9531101', 'C002', '87.0');
          INSERT INTO sc VALUES ('9531101', 'C003', '95.0');
          INSERT INTO sc VALUES ('9531101', 'C004', '76.0');
          INSERT INTO sc VALUES ('9531102', 'C001', null);
          INSERT INTO sc VALUES ('9531102', 'C002', '87.0');
          INSERT INTO sc VALUES ('9531102', 'C003', '95.0');
          INSERT INTO sc VALUES ('9531102', 'C004', '76.0');
          INSERT INTO sc VALUES ('9531102', 'C005', '94.0');
          

          2. 演示说明

          我用的是navicat数据库,下面具体演示一下如何将数据导入到navicat数据库中

          1. 新建一个数据库,取名 “student”,字符集选 utf8,然后点击确定。

            创建

          2. 打开刚刚创建的student数据库,点击"查询",然后点击"新建查询"。

            查询

          3. 将以上MySQL语句复制黏贴到数据库中,点击运行即可。

            运行

          4. 等程序运行完成后,点击左侧的表并刷新一下,此时就会出现刚才创建的所有表了。

            表

          Python程序设计部分

          1. 连接数据库

          程序设计

          import pymysql
          Username = ""
          Findsno = ""
          Findcno = ""
          def conn():  # 连接数据库
              db = pymysql.connect(host="localhost", user="root", database="student", charset='utf8')
              return db
          def update(sql, *values):  # shift键,单tab
              db1 = conn()
              cursor1 = db1.cursor()
              try:
                  cursor1.execute(sql, values)
                  db1.commit()
                  return 1
              except:
                  db1.rollback()
                  return 0
              finally:
                  cursor1.close()
                  db1.close()
          def update2(sql):  # shift键,单tab
              db1 = conn()
              cursor1 = db1.cursor()
              try:
                  cursor1.execute(sql)
                  db1.commit()
                  return 1
              except:
                  db1.rollback()
                  return 0
              finally:
                  cursor1.close()
                  db1.close()
          def query(sql, *keys):
              db2 = conn()
              cursor2 = db2.cursor()
              cursor2.execute(sql, keys)
              rs = cursor2.fetchall()
              cursor2.close()
              db2.close()
              return rs
          def query2(sql):
              db3 = conn()
              cursor3 = db3.cursor()
              cursor3.execute(sql)
              rs = cursor3.fetchall()
              row = cursor3.rowcount
              cursor3.close()
              db3.close()
              return rs, row
          

          程序分析

          在python中,我们使用了pymysql模块来连接MySQL数据库,并提供了一系列的函数来执行数据库操作。下面是对代码中各个函数的具体分析:

          conn()函数

          该函数用来连接到MySQL数据库,并返回一个数据库连接对象。

          update()函数

          该函数用来执行DML语句(如INSERT、UPDATE、DELETE等),可以使用占位符参数(*values)来代替SQL语句中的参数,函数会自动替换,防止SQL注入攻击。

          update2()函数

          该函数同样用来执行DML语句,但不需要使用占位符参数,因为这种情况下SQL语句中没有参数,所以直接执行即可。

          query()函数

          该函数用来执行SQL查询语句,并可以使用占位符参数来代替SQL语句中的参数。函数会返回所有匹配的结果集(即fetchall)。

          query2()函数

          该函数同样用来执行SQL查询语句,但不需要使用占位符参数,因为这种情况下SQL语句中没有参数,所以直接执行即可。函数会返回所有匹配的结果集和行数(即fetchall和rowcount)。

          2. 登录界面

          效果

          登录

          程序设计

          import tkinter as tk
          import tkinter.messagebox
          import db
          import mainWin
          import register
          # 登录界面
          class Login():
              def __init__(self):
                  self.root2 = tk.Tk()
                  self.root2.title("登陆")
                  self.screenwidth = self.root2.winfo_screenwidth()
                  self.screenheight = self.root2.winfo_screenheight()
                  self.root2.geometry('%dx%d+%d+%d' % (400, 200, (self.screenwidth - 400) / 2, (self.screenheight - 200) / 2))
                  self.label = tk.Label(self.root2, text='登录系统', font=("黑体", 25))
                  self.label.place(x=125, y=10)
                  self.userlabel = tk.Label(self.root2, text="用户名:", font=("黑体", 15))
                  self.userlabel.place(x=80, y=60)
                  self.userentry = tk.Entry(self.root2)
                  self.userentry.place(x=160, y=62)
                  self.pwdlabel = tk.Label(self.root2, text="密  码:", font=("黑体", 15))
                  self.pwdlabel.place(x=80, y=100)
                  self.pwdentry = tk.Entry(self.root2, width=20, show='*')
                  self.pwdentry.place(x=160, y=102)
                  self.userentry.insert(0, 'user01')
                  self.pwdentry.insert(0, '123')
                  self.okbutton = tk.Button(self.root2, text='提交', font=10, command=self.openMain)
                  self.okbutton.place(x=70, y=140)
                  self.cancelbutton = tk.Button(self.root2, text='取消', font=10, command=self.root2.destroy)
                  self.cancelbutton.place(x=170, y=140)
                  self.addbutton = tk.Button(self.root2, text='注册', font=10, command=self.adduser)
                  self.addbutton.place(x=270, y=140)
                  self.root2.mainloop()
              def openMain(self):
                  username2 = self.userentry.get()
                  userpwd2 = self.pwdentry.get()
                  if username2.strip() == "" or userpwd2.strip() == "":
                      tk.messagebox.showerror("登录失败", "用户名或密码不能为空")
                      return False
                  else:
                      try:
                          rs = db.query("select * from users where username = %s and passwords = %s", username2, userpwd2)
                          if len(rs) > 0:
                              db.Username = username2
                              self.root2.destroy()
                              mainWin.MainWin()
                          else:
                              tk.messagebox.showinfo("ee", "你输入的信息不正确,请重新输入")
                      except Exception as e:
                          print("登陆异常")
                          print(e)
              def adduser(self):
                  self.root2.destroy()
                  register.Register()
          

          程序分析

          这是一个使用Tkinter编写的用户登录界面程序。程序主要分为两部分,即界面设计和响应事件处理。

          在界面设计部分,代码使用了Tkinter的各种控件,包括Label、Entry、Button等,用于显示和接收用户输入信息。具体设计如下:

          1. 创建一个顶级窗口root2,并设置标题和窗口大小。
          2. 在窗口上添加一个Label控件,用于显示“登录系统”。
          3. 添加两个Label控件和两个Entry控件,用于接收用户名和密码,并初始化默认值。
          4. 添加三个Button控件,分别用于提交、取消和注册操作。

          在响应事件处理部分,代码使用了各种函数来实现登录和注册功能:

          1. openMain()函数用于处理提交操作,获取用户输入的用户名和密码,并按照先验证是否为空,再验证是否存在于数据库中。最后,如果登录成功则跳转到主界面,否则给出相应提示。
          2. adduser()函数用于处理注册操作,当用户按下“注册”按钮时,关闭当前登录窗口(root2),并跳转到注册界面。

          程序中还调用了db.py模块,实现数据库操作。

          3. 注册界面

          效果

          注册

          程序设计

          import tkinter as tk
          import tkinter.messagebox
          import db
          import login
          class Register():
              def __init__(self):
                  self.root1 = tk.Tk()
                  self.root1.title("新用户注册")
                  self.screenwidth = self.root1.winfo_screenwidth()
                  self.screenheight = self.root1.winfo_screenheight()
                  self.root1.geometry('%dx%d+%d+%d' % (400, 200, (self.screenwidth - 400) / 2, (self.screenheight - 200) / 2))
                  self.label = tk.Label(self.root1, text='注册系统', font=("黑体", 25))
                  self.label.place(x=125, y=10)
                  self.userlabel = tk.Label(self.root1, text="用户名:", font=("黑体", 15))
                  self.userlabel.place(x=80, y=60)
                  self.userentry = tk.Entry(self.root1)
                  self.userentry.place(x=160, y=62)
                  self.pwdlabel = tk.Label(self.root1, text="密  码:", font=("黑体", 15))
                  self.pwdlabel.place(x=80, y=100)
                  self.pwdentry = tk.Entry(self.root1, width=20, show='*')
                  self.pwdentry.place(x=160, y=102)
                  self.okbutton = tk.Button(self.root1, text='提交', font=("黑体", 15), command=self.addUser)
                  self.okbutton.place(x=70, y=140)
                  self.cancelbutton = tk.Button(self.root1, text='取消', font=("黑体", 15), command=self.root1.destroy)
                  self.cancelbutton.place(x=170, y=140)
                  self.loginbutton = tk.Button(self.root1, text='登陆', font=("黑体", 15), command=self.loginUser)
                  self.loginbutton.place(x=270, y=140)
                  self.root1.mainloop()
              def addUser(self):
                  username1 = self.userentry.get()
                  userpwd1 = self.pwdentry.get()
                  if username1.strip() == "" or userpwd1.strip() == "":
                      tk.messagebox.showerror("警告", "用户名或密码不能为空")
                      return False
                  else:
                      rs1 = db.query('select * from users where username=%s', username1)
                      if len(rs1) > 0:
                          tk.messagebox.showinfo("注册失败", "该用户名已经存在")
                          self.userentry.delete(0)
                          self.pwdentry.delete(0)
                      else:
                          rs = db.update("insert into users(username,passwords) values(%s,%s)", username1, userpwd1)
                          if rs > 0:
                              tk.messagebox.showinfo("用户", "添加成功")
                          else:
                              self.userentry.delete(0)
                              self.pwdentry.delete(0)
              def loginUser(self):
                  self.root1.destroy()
                  login.Login()
          

          程序分析

          这是一个使用Tkinter编写的用户注册界面程序。程序主要分为两部分,即界面设计和响应事件处理。

          在界面设计部分,代码使用了Tkinter的各种控件,包括Label、Entry、Button等,用于显示和接收用户输入信息。具体设计如下:

          1. 创建一个顶级窗口root1,并设置标题和窗口大小。
          2. 在窗口上添加一个Label控件,用于显示“注册系统”。
          3. 添加两个Label控件和两个Entry控件,用于接收用户名和密码。
          4. 添加三个Button控件,分别用于提交、取消和登录操作。

          在响应事件处理部分,代码使用了各种函数来实现用户注册和登录功能:

          1. addUser()函数用于处理提交操作,获取用户输入的用户名和密码,并按照先验证是否为空,再验证是否已经存在于数据库中。最后,将用户名和密码插入到数据库中,并给出相应提示。
          2. loginUser()函数用于处理登录操作,当用户按下“登录”按钮时,关闭当前注册窗口(root1),并跳转到登录界面。

          程序中还调用了db.py模块,实现数据库操作。

          4. 主界面

          效果

          主界面

          程序设计

          import tkinter as tk
          import numpy as np
          import register
          import selUser
          import login
          import findSno
          import updPwd
          import findCno
          import db
          class MainWin():
              def __init__(self):
                  self.root3 = tk.Tk()
                  self.root3.title("成绩分析")
                  self.screenwidth = self.root3.winfo_screenwidth()
                  self.screenheight = self.root3.winfo_screenheight()
                  self.root3.geometry('%dx%d+%d+%d' % (500, 300, (self.screenwidth - 500) / 2, (self.screenheight - 300) / 2))
                  menu1 = tk.Menu(self.root3)
                  menu1_2 = tk.Menu(menu1, tearoff=False)  # 创建二级菜单
                  menu1.add_cascade(label="用户管理", menu=menu1_2)  # 创建级联菜单
                  menu1_2.add_command(label='用户注册', command=self.adduser)
                  menu1_2.add_command(label='密码修改', command=self.updPwd)
                  menu1_2.add_command(label='查询用户信息', command=self.seluser)
                  menu1_2.add_command(label='重新登录', command=self.loginuser)
                  menu1.add_command(label='退出系统', command=self.root3.quit)
                  self.root3.config(menu=menu1_2)
                  self.root3.config(menu=menu1)  # 显示菜单
                  self.finds = tk.Label(self.root3, text='成绩分析', font=("黑体", 20))
                  self.finds.place(x=180, y=30)
                  self.student_sno = tk.Label(self.root3, text='请输入要查询成绩的学生学号:', font=("黑体", 12))
                  self.student_sno.place(x=50, y=100)
                  self.entry_sno = tk.Entry(self.root3)
                  self.entry_sno.place(x=280, y=100)
                  self.find_sgrade = tk.Button(self.root3, text='查询', font=("黑体", 15), command=self.findsno)
                  self.find_sgrade.place(x=200, y=130)
                  self.student_cno = tk.Label(self.root3, text='请输入要查询成绩的课程代号:', font=("黑体", 12))
                  self.student_cno.place(x=50, y=200)
                  self.entry_cno = tk.Entry(self.root3)
                  self.entry_cno.place(x=280, y=200)
                  self.find_cgrade = tk.Button(self.root3, text='查询', font=("黑体", 15), command=self.findcno)
                  self.find_cgrade.place(x=200, y=230)
                  self.root3.mainloop()
              def adduser(self):
                  self.root3.destroy()
                  register.Register()
              def loginuser(self):
                  self.root3.destroy()
                  login.Login()
              def seluser(self):
                  selUser.SelUser()
              def updPwd(self):
                  self.root3.destroy()
                  updPwd.UpdPWD()
              def findsno(self):
                  fsno = self.entry_sno.get()
                  snos = np.array(db.query("select sno from sc"))[:, 0]
                  if fsno.strip() not in snos:
                      tk.messagebox.showerror("警告", "该用户不存在成绩!")
                      return False
                  else:
                      db.Findsno = fsno
                      findSno.Manage()
              def findcno(self):
                  fcno = self.entry_cno.get()
                  cnos = np.array(db.query("select grade from sc where cno=%s and grade is not null", fcno))
                  print(cnos)
                  if len(cnos) == 0:
                      tk.messagebox.showerror("警告", "该课程不存在成绩!")
                      return False
                  else:
                      db.Findcno = fcno
                      findCno.Manage()
          

          程序分析

          这是一个使用Tkinter编写的成绩分析界面程序。程序主要分为两部分,即界面设计和响应事件处理。

          在界面设计部分,代码使用了Tkinter的各种控件,包括Label、Entry、Button等,用于显示和接收用户输入信息,同时也添加了菜单栏,用于管理用户信息。具体设计如下:

          1. 创建一个顶级窗口root3,并设置标题和窗口大小。
          2. 创建一个菜单栏menu1,并添加一个级联菜单menu1_2,包含用户注册、密码修改、查询用户信息和重新登录功能。
          3. 添加一个Label控件,用于显示“成绩分析”。
          4. 添加两个Label控件和两个Entry控件,用于接收学号和课程代码。
          5. 添加两个Button控件,分别用于查询学生成绩和查询课程成绩。

          在响应事件处理部分,代码使用了各种函数来实现各种功能:

          1. adduser()函数用于处理用户注册操作,当用户按下“用户注册”按钮时,关闭当前成绩分析窗口(root3),并跳转到注册界面。
          2. loginuser()函数用于处理重新登录操作,当用户按下“重新登录”按钮时,关闭当前成绩分析窗口(root3),并返回到登录界面。
          3. seluser()函数用于处理查询用户信息操作,当用户按下“查询用户信息”按钮时,弹出窗口,显示用户信息。
          4. updPwd()函数用于处理密码修改操作,当用户按下“密码修改”按钮时,关闭当前成绩分析窗口(root3),并跳转到密码修改界面。
          5. findsno()函数用于处理查询学生成绩操作,获取用户输入的学号,按照先验证学号是否存在于数据库中,如果存在则将学号传递至查询学生成绩的界面,如果不存在则给出相应提示。
          6. findcno()函数用于处理查询课程成绩操作,获取用户输入的课程代码,按照先验证课程代码是否存在于数据库中,如果存在则将课程代码传递至查询课程成绩的界面,如果不存在则给出相应提示。

          程序中还调用了db.py。

          5. 查询信息

          效果

          查询

          程序设计

          import tkinter as tk
          import tkinter.ttk as ttk
          import db
          class SelUser():
              def __init__(self):
                  self.root4 = tk.Tk()  # 创建根窗口
                  self.root4.title("查询用户信息")  # 设置窗口标题
                  self.screenwidth = self.root4.winfo_screenwidth()
                  self.screenheight = self.root4.winfo_screenheight()
                  self.root4.geometry('%dx%d+%d+%d' % (400, 250, (self.screenwidth - 400) / 2, (self.screenheight - 250) / 2))
                  self.create_gui()  # 调用窗口组件函数
                  self.root4.mainloop()  # 让程序继续执行,直到窗口关闭
              def create_gui(self):  # 定义图形用户界面函数
                  self.create_top_right_labelframe()  # 查询条件组件设置
                  self.create_records_treeview()  # 查询结果树形菜单组件设置
              def create_top_right_labelframe(self):  # 查询条件组件界面
                  labelframe1 = tk.LabelFrame(self.root4, text='用户信息', width=400)  # 标签框架组件
                  labelframe1.grid(row=0, column=1, sticky='ew', padx=8, pady=8)
                  tk.Label(labelframe1, text='  账号:').grid(row=1, column=1, sticky='w', pady=2)  # 账号标签
                  self.namefield = tk.Entry(labelframe1)  # 账号输入框
                  self.namefield.grid(row=1, column=2, sticky='w', padx=5, pady=2)
                  tk.Label(labelframe1, text='  密码:').grid(row=2, column=1, sticky='w', pady=2)
                  self.numfield = tk.Entry(labelframe1)
                  self.numfield.grid(row=2, column=2, sticky='w', padx=5, pady=2)
                  tk.Button(labelframe1, text='查询', command=self.seluser).grid(row=3, column=1, sticky='e', padx=5, pady=2)
              def create_records_treeview(self):  # 显示记录信息
                  treeview_columns = ['userId', 'userName', 'userPwd']
                  self.record_treeview = ttk.Treeview(self.root4, show='headings', height=5, columns=treeview_columns)
                  self.record_treeview.grid(row=4, column=0, columnspan=3)
                  self.record_treeview.heading('userId', text='序号')
                  self.record_treeview.heading('userName', text='用户名')
                  self.record_treeview.heading('userPwd', text='密码')  # , anchor='center'
                  self.record_treeview.column('userId', width=100)
                  self.record_treeview.column('userName', width=120)
                  self.record_treeview.column('userPwd', width=220)
              def seluser(self):
                  username3 = self.namefield.get()
                  userpwd3 = self.numfield.get()
                  if username3.strip() == "" or userpwd3.strip() == "":
                      tk.messagebox.showerror("警告", "用户名或密码不能为空")
                      return False
                  else:
                      rs, row = db.query2(
                          "select * from users where username like '%" + username3 + "%' and passwords like '%" + userpwd3 + "%'")
                      if row == 0:
                          tk.messagebox.showerror("警告", "该用户名或密码不存在")
                          return False
                      else:
                          for i in range(row):
                              self.record_treeview.insert("", 'end', values=rs[i])
          

          程序分析

          这段代码是一个查询用户信息的窗口,使用了tkinter来创建GUI界面,并且使用了MySQL数据库进行数据查询。其中包括如下函数:

          1. __init__(self)
          • 创建根窗口
          • 设置窗口标题
          • 获取屏幕宽高
          • 调用create_gui()创建窗口组件
          • 执行mainloop()让程序继续执行
            1. create_gui(self)
            • 调用create_top_right_labelframe()创建查询条件组件
            • 调用create_records_treeview()创建查询结果树形菜单组件
              1. create_top_right_labelframe(self)
              • 创建标签框架组件
              • 创建账号和密码标签
              • 创建输入框和查询按钮
              • 将查询按钮与seluser()函数绑定
                1. create_records_treeview(self)
                • 创建树形菜单组件
                • 设置树形菜单展示的列和标题
                • 设置树形菜单每列的宽度
                  1. seluser(self)
                  • 获取输入的账号和密码信息
                  • 判断输入是否为空,如果为空则弹窗警告
                  • 如果输入不为空则调用db.query2函数进行数据库查询
                  • 如果查询结果为空则弹窗警告
                  • 如果查询结果不为空则遍历查询结果并添加到树形菜单中

                    总结:这段代码主要是使用了tkinter和MySQL实现了查询用户信息的功能,并且使用了GUI界面进行操作和显示。

                    6. 修改密码

                    效果

                    修改密码

                    程序设计

                    import tkinter as tk
                    import tkinter.messagebox
                    import db
                    import mainWin
                    class UpdPWD():
                        def __init__(self):
                            self.aa = db.Username
                            self.root6 = tk.Tk()
                            self.screenwidth = self.root6.winfo_screenwidth()
                            self.screenheight = self.root6.winfo_screenheight()
                            self.root6.geometry('%dx%d+%d+%d' % (400, 200, (self.screenwidth - 400) / 2, (self.screenheight - 200) / 2))
                            self.root6.title("密码修改窗口")
                            self.namelabel = tk.Label(self.root6, text='账号:', font=("黑体", 15))
                            self.namelabel.place(x=80, y=20)
                            self.nametxt = tk.Entry(self.root6)
                            self.nametxt.place(x=140, y=22)
                            self.nametxt.insert(0, self.aa)
                            self.labelpwd1 = tk.Label(self.root6, text='密码:', font=("黑体", 15))
                            self.labelpwd1.place(x=80, y=60)
                            self.pwd1 = tk.Entry(self.root6)
                            self.pwd1.place(x=140, y=62)
                            self.labelpwd2 = tk.Label(self.root6, text='确认密码:', font=("黑体", 12))
                            self.labelpwd2.place(x=60, y=100)
                            self.pwd2 = tk.Entry(self.root6)
                            self.pwd2.place(x=140, y=102)
                            self.button = tk.Button(self.root6, text="确定", font=("黑体", 15), command=self.updpwd)
                            self.button.place(x=100, y=140)
                            self.button2 = tk.Button(self.root6, text="主窗口", font=("黑体", 15), command=self.returnwin)
                            self.button2.place(x=200,y=140)
                            self.root6.mainloop()
                        def updpwd(self):
                            bb = self.pwd1.get()
                            aa = self.aa
                            print(aa)
                            print(bb)
                            rs = db.update2("update tb_user set username='" + bb + "' where passwords='" + aa + "'")
                            print(rs)
                            if rs > 0:
                                tk.messagebox.showinfo("提示消息", "密码修改成功")
                            else:
                                tk.messagebox.showinfo("提示消息", "修改失败")
                                self.pwd1.delete(0)
                                self.pwd2.delete(0)
                        def returnwin(self):
                            self.root6.destroy()
                            mainWin.MainWin()
                    

                    程序分析

                    这是一个基于tkinter GUI库实现的密码修改窗口类(UpdPWD)。

                    首先,在类的构造函数中,该类初始化了界面窗口(self.root6),设置窗口标题和尺寸,以及创建并放置标签(Label)和输入框(Entry)。

                    然后,在 updpwd() 方法中,该类获取输入框中的新密码,并将其通过执行数据库更新操作(update2()),更新到原先密码对应的账号上,如果更新成功,则弹出 “密码修改成功” 的提示框,否则弹出 “修改失败” 的提示框,并清空密码输入框。

                    最后,在 returnwin() 方法中,该类关闭当前窗口,并打开主窗口(MainWin)。

                    总的来说,该类实现了密码修改窗口的基本功能,并通过调用数据库进行数据更新操作,并添加了错误提示信息和返回主窗口按钮。同时,该类的代码结构比较清晰,易于理解和维护。

                    7. 成绩分析

                    7.1 通过学号查询成绩

                    效果

                    成绩1

                    程序设计

                    import tkinter as tk
                    import matplotlib.pyplot as plt
                    import numpy as np
                    import matplotlib
                    import db
                    from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
                    from matplotlib.figure import Figure
                    plt.rcParams['font.sans-serif'] = ['SimHei']
                    plt.rcParams['axes.unicode_minus'] = False
                    class Manage():
                        def __init__(self):
                            matplotlib.use("TkAgg")
                            self.root7 = tk.Tk()
                            self.root7.title("学生成绩分析")
                            self.screenwidth = self.root7.winfo_screenwidth()
                            self.screenheight = self.root7.winfo_screenheight()
                            self.root7.geometry('%dx%d+%d+%d' % (400, 350, (self.screenwidth - 400) / 2, (self.screenheight - 350) / 2))
                            f = Figure(figsize=(5, 4), dpi=85)
                            a = f.add_subplot(111)
                            find_name = db.Findsno
                            data = db.query("select * from sc where %s=sno and grade is not null", find_name)
                            x = np.array(data)[:, 1]
                            y = np.array(data)[:, 2].astype(int)
                            a.plot(x, y, marker='o', color='red', label='成绩')
                            for m, n in zip(x, y):
                                a.text(m, n, n, ha='center', va='bottom', fontsize=12)
                            a.set_title("学生%s成绩情况折线图" % find_name, fontsize=12)
                            a.set_yticks(np.arange(0, 105, 10))
                            a.set_xlabel("课程号", fontsize=12)
                            a.set_ylabel("成绩", fontsize=12)
                            a.legend(loc='lower right')
                            canvas = FigureCanvasTkAgg(f, self.root7)
                            canvas.draw()
                            canvas.get_tk_widget().pack()
                            canvas._tkcanvas.pack()
                            self.root7.mainloop()
                    

                    程序分析

                    这段代码是一个可视化学生成绩的窗口,使用了tkinter和matplotlib库来创建GUI界面和绘制折线图。具体分析如下:

                    1. init(self)
                    • 创建根窗口
                    • 设置窗口标题
                    • 获取屏幕宽高
                    • 创建Figure对象,设置图形大小和分辨率
                    • 调用add_subplot()方法创建子图
                    • 调用db.Findsno获取学生学号,调用db.query查询该学生的成绩
                    • 将查询结果存储在numpy数组中
                    • 调用plot()方法绘制折线图
                    • 调用text()方法给每个点添加标签
                    • 调用设置子图标题、x轴、y轴标签和图例等属性
                    • 调用FigureCanvasTkAgg()方法将图形绘制到GUI界面上
                      1. canvas.draw()
                      • 绘制图形
                        1. canvas.get_tk_widget().pack()
                        • 显示GUI界面
                          1. canvas._tkcanvas.pack()
                          • 将tkinter版的canvas嵌入GUI中

                            总结:这段代码主要是使用了matplotlib库来绘制折线图,并且使用了tkinter库创建GUI界面,实现了可视化学生成绩的功能,方便用户查看分析。

                            7.2 通过课程号查询成绩

                            效果

                            成绩2

                            程序设计

                            import tkinter as tk
                            import matplotlib.pyplot as plt
                            import numpy as np
                            import matplotlib
                            import db
                            from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
                            from matplotlib.figure import Figure
                            plt.rcParams['font.sans-serif'] = ['SimHei']
                            plt.rcParams['axes.unicode_minus'] = False
                            class Manage():
                                def __init__(self):
                                    matplotlib.use("TkAgg")
                                    self.root5 = tk.Tk()
                                    self.root5.title("课程成绩分析")
                                    self.screenwidth = self.root5.winfo_screenwidth()
                                    self.screenheight = self.root5.winfo_screenheight()
                                    self.root5.geometry('%dx%d+%d+%d' % (400, 350, (self.screenwidth - 400) / 2, (self.screenheight - 350) / 2))
                                    f = Figure(figsize=(5, 4), dpi=85)
                                    a = f.add_subplot(111)
                                    find_name = db.Findcno
                                    data = db.query("select * from sc where %s=cno and grade is not null", find_name)
                                    x = np.array(data)[:, 0]
                                    y = np.array(data)[:, 2].astype(int)
                                    a.plot(x, y, marker='o', color='blue', label='成绩')
                                    for m, n in zip(x, y):
                                        a.text(m, n, n, ha='center', va='bottom', fontsize=12)
                                    a.set_title("课程%s成绩情况折线图" % find_name, fontsize=12)
                                    a.set_yticks(np.arange(0, 105, 10))
                                    a.set_xlabel("课程号", fontsize=12)
                                    a.set_ylabel("成绩", fontsize=12)
                                    a.legend(loc='lower right')
                                    canvas = FigureCanvasTkAgg(f, self.root5)
                                    canvas.draw()
                                    canvas.get_tk_widget().pack()
                                    canvas._tkcanvas.pack()
                                    self.root5.mainloop()
                            

                            程序分析

                            这段代码是一个可视化课程成绩的窗口,与可视化学生成绩的窗口十分类似。具体分析如下:

                            1. init(self)
                            • 创建根窗口
                            • 设置窗口标题
                            • 获取屏幕宽高
                            • 创建Figure对象,设置图形大小和分辨率
                            • 调用add_subplot()方法创建子图
                            • 调用db.Findcno获取课程号,调用db.query查询该课程的成绩
                            • 将查询结果存储在numpy数组中
                            • 调用plot()方法绘制折线图
                            • 调用text()方法给每个点添加标签
                            • 调用设置子图标题、x轴、y轴标签和图例等属性
                            • 调用FigureCanvasTkAgg()方法将图形绘制到GUI界面上
                              1. canvas.draw()
                              • 绘制图形
                                1. canvas.get_tk_widget().pack()
                                • 显示GUI界面
                                  1. canvas._tkcanvas.pack()
                                  • 将tkinter版的canvas嵌入GUI中

                                    总结:这段代码与可视化学生成绩的窗口十分类似,主要是使用了matplotlib库来绘制折线图,并且使用了tkinter库创建GUI界面,实现了可视化课程成绩的功能,方便用户查看分析。

                                    7. 主函数

                                    import login
                                    #主函数
                                    if __name__ == "__main__":
                                        login.Login()
                                    

                                    尾声

                                    该学生成绩管理系统需要有一些Python程序设计、Python数据分析以及MySQL数据库的基础,相信大家在亲自完成这个项目之后,一定收获不小吧!