学生管理系统-Python tkinter图形化界面+mysql+柱状图

通过python图形化界面和数据库实现学生成绩管理系统

实现功能大概如下:

  1. 基本功能增删改查
  2. 限制成绩在各种情况下只能为0-100
  3. 实现成绩的统计功能(柱状图显示)
  4. 筛选各个成绩区间的学生信息
  5. 实现排序功能
  6. 登录注册功能
  7. 对各种错误进行捕获

项目部分效果展示

学生管理系统-Python tkinter图形化界面+mysql+柱状图_第1张图片学生管理系统-Python tkinter图形化界面+mysql+柱状图_第2张图片学生管理系统-Python tkinter图形化界面+mysql+柱状图_第3张图片学生管理系统-Python tkinter图形化界面+mysql+柱状图_第4张图片学生管理系统-Python tkinter图形化界面+mysql+柱状图_第5张图片学生管理系统-Python tkinter图形化界面+mysql+柱状图_第6张图片

登录注册模块代码

from database import *
from win import *


class Login:
    def __init__(self):
        """创建登录界面"""
        self.db = Database()
        # 创建主窗口,用于容纳其它组件
        self.login_root = Tk()
        # 给主窗口设置标题内容
        self.login_root.title("登录系统")
        # 设置窗口大小和位置
        screenwidth = self.login_root.winfo_screenwidth()
        screenheight = self.login_root.winfo_screenheight()
        width = 500
        high = 300
        self.login_root.geometry('%dx%d+%d+%d' % (width, high, (screenwidth - width) / 2, (screenheight - high) / 2))

        # 创建画布
        self.canvas = Canvas(self.login_root, height=400, width=700)
        self.image_file = PhotoImage(file="123.gif")
        # 加载图片文件,并将图片置于画布上
        self.image = self.canvas.create_image(0, 0, anchor='nw', image=self.image_file)
        # 放置画布(为上端)
        self.canvas.pack(side='top')

        # 创建账户标签
        Label(self.login_root, text='账户').place(x=90, y=70)
        # 创建密码标签
        Label(self.login_root, text='密码').place(x=90, y=95)

        account = StringVar()
        password = StringVar()
        # 创建一个账号输入框,并设置尺寸
        Entry(self.login_root, width=30, textvariable=account).place(x=140, y=70)
        # 创建一个密码输入框,并设置尺寸
        Entry(self.login_root, show='*', width=30, textvariable=password).place(x=140, y=95)

        # 创建一个登录系统的按钮
        Button(self.login_root, command=lambda: self.login(account, password), text="登录", width=10).place(x=155, y=120)
        # 创建一个注册系统的按钮
        Button(self.login_root, command=lambda: self.register(account, password), text="注册", width=10).place(x=250, y=120)

        mainloop()

    def login(self, account, password):
        """登录功能实现"""
        account = account.get()
        password = password.get()
        if account.strip() and password.strip():
            if self.db.prepare(f"select * from stu_user where stu_account='{account}' and stu_password='{password}'"):
                showinfo("提示", "登录成功")
                self.login_root.destroy()
                Win()
            else:
                showerror("错误", "密码或账号错误请重新输入")
        else:
            showerror("错误", "账号信息没有输入完整")
    def register(self, account, password):
        """注册功能实现"""
        account = account.get()
        password = password.get()
        # 判断信息是否输入完整
        if account.strip() and password.strip():
            if self.db.prepare(f"select * from stu_user where stu_account='{account}'") == 0:
                self.db.prepare(f"insert into stu_user values ('{account}', '{password}')")
                showinfo("提示", "注册成功")
            else:
                showerror("错误", "该账号已被注册")
        else:
            showerror("错误", "请输入完整的账号信息")

数据库模块代码

import MySQLdb


class Database(object):
    def __init__(self):
        """连接数据库"""
        self.db = MySQLdb.connect("localhost", "root", "1535258", "manage", charset='utf8')
        self.cursor = self.db.cursor()

    def prepare(self, sql):
        """执行sql语句"""
        return self.cursor.execute(sql)

    def update(self):
        """提交到数据库执行"""
        self.db.commit()

    def close(self):
        """关闭数据库"""
        self.db.close()

主窗口模块代码

from tkinter import *
from tkinter import ttk
from tkinter.messagebox import *
from show_info import ShowInfo
from modify_info import ModifyInfo
from search_info import SearchInfo
from del_info import DelInfo
from statistics_info import StatisticsInfo
from add_info import AddInfo
from sort import TreeviewSortColumn
from section_query import SectionQuery


class Win(object):
    def __init__(self):
        """主界面基本设置"""
        # 创建窗口
        root = Tk()
        # 设置窗口大小和并将位置设置到屏幕中央
        screenwidth = root.winfo_screenwidth()
        screenheight = root.winfo_screenheight()
        width = 700
        high = 600
        root.geometry('%dx%d+%d+%d' % (width, high, (screenwidth - width) / 2, (screenheight - high) / 2))

        root.title('学生管理系统')

        # 设置各个文本框的标签,并固定位置
        Label(root, text="学号:").place(relx=0, rely=0.05, relwidth=0.1)
        Label(root, text="姓名:").place(relx=0.5, rely=0.05, relwidth=0.1)
        Label(root, text="Python:").place(relx=0, rely=0.1, relwidth=0.1)
        Label(root, text="C语言:").place(relx=0.5, rely=0.1, relwidth=0.1)

        # 设置各个文本框内容所对应的变量
        self.stu_id = StringVar()
        self.stu_name = StringVar()
        self.stu_python = StringVar()
        self.stu_c = StringVar()

        # 设置各个文本框并固定位置
        Entry(root, textvariable=self.stu_id).place(relx=0.1, rely=0.05, relwidth=0.35, height=25)
        Entry(root, textvariable=self.stu_name).place(relx=0.6, rely=0.05, relwidth=0.35, height=25)
        Entry(root, textvariable=self.stu_python).place(relx=0.1, rely=0.1, relwidth=0.35, height=25)
        Entry(root, textvariable=self.stu_c).place(relx=0.6, rely=0.1, relwidth=0.35, height=25)

        # 设置窗口的标题标签
        Label(root, text='学生信息管理', bg='white', fg='red', font=('宋体', 15)).pack(side=TOP, fill='x')

        # 创建表格并设置相关属性
        self.tree_view = ttk.Treeview(root, show='headings', column=('stu_id', 'stu_name', 'stu_python', 'stu_c'))
        sb = Scrollbar(root, orient='vertical', command=self.tree_view.yview)
        sb.place(relx=0.971, rely=0.028, relwidth=0.024, relheight=0.958)
        # 设置每列的属性
        self.tree_view.configure(yscrollcommand=sb.set)
        self.tree_view.column('stu_id', width=150, anchor="center")
        self.tree_view.column('stu_name', width=150, anchor="center")
        self.tree_view.column('stu_python', width=150, anchor="center")
        self.tree_view.column('stu_c', width=150, anchor="center")
        # 设置每行的属性
        self.tree_view.heading('stu_id', text='学号', command=lambda: TreeviewSortColumn().table_sort(self.tree_view, 'stu_id', False))
        self.tree_view.heading('stu_name', text='姓名', command=lambda: TreeviewSortColumn().table_sort(self.tree_view, 'stu_name', False))
        self.tree_view.heading('stu_python', text='Python', command=lambda: TreeviewSortColumn().table_sort(self.tree_view, 'stu_python', False))
        self.tree_view.heading('stu_c', text='C语言', command=lambda: TreeviewSortColumn().table_sort(self.tree_view, 'stu_c', False))
        # 设置表格位置
        self.tree_view.place(relx=0.02, rely=0.3, relwidth=0.96)

        # 设置按钮,并固定位置
        Button(root, text="显示所有信息", command=lambda: ShowInfo(self.tree_view)).place(relx=0.05, rely=0.2, width=80)
        Button(root, text="添加学生信息", command=lambda: AddInfo(self.stu_id, self.stu_name, self.stu_python, self.stu_c)).place(relx=0.20, rely=0.2, width=80)
        Button(root, text="删除学生信息", command=lambda: DelInfo(self.stu_id, self.stu_name, self.stu_python, self.stu_c)).place(relx=0.35, rely=0.2, width=80)
        Button(root, text="修改学生信息", command=lambda: ModifyInfo(self.stu_id, self.stu_name, self.stu_python, self.stu_c)).place(relx=0.50, rely=0.2, width=80)
        Button(root, text="统计学生信息", command=lambda: StatisticsInfo()).place(relx=0.65, rely=0.2, width=80)
        Button(root, text="查询学生信息", command=lambda: SearchInfo(self.stu_id, self.stu_name, self.stu_python, self.stu_c, self.tree_view)).place(relx=0.80, rely=0.2, width=80)

        # 创建一个顶级菜单
        menubar = Menu(root)

        # 创建下拉菜单,然后将它添加到顶级菜单中
        filemenu = Menu(menubar, tearoff=False)
        section_menu = Menu(filemenu, tearoff=False)
        python_menu = Menu(section_menu, tearoff=False)
        c_menu = Menu(section_menu, tearoff=False)
        total_menu = Menu(filemenu, tearoff=False)

        # 设置下拉菜单的label
        menubar.add_cascade(label="选项", menu=filemenu)
        filemenu.add_cascade(label="分段筛选数据", menu=section_menu)
        filemenu.add_cascade(label="按总成绩排序", menu=total_menu)
        filemenu.add_separator()
        filemenu.add_command(label="退出", command=lambda: self.callback(root))
        section_menu.add_cascade(label="Python", menu=python_menu)
        section_menu.add_cascade(label="C语言", menu=c_menu)
        section_menu.add_command(label="自定义区间", command=lambda: SectionQuery(self.tree_view).custom(self.tree_view))
        python_menu.add_command(label="0-60", command=lambda: SectionQuery(self.tree_view).section(self.tree_view, 'python', 0, 60))
        python_menu.add_command(label="60-80", command=lambda: SectionQuery(self.tree_view).section(self.tree_view, 'python', 60, 80))
        python_menu.add_command(label="80-100", command=lambda: SectionQuery(self.tree_view).section(self.tree_view, 'python', 80, 100))
        c_menu.add_command(label="0-60", command=lambda: SectionQuery(self.tree_view).section(self.tree_view, 'c', 0, 60))
        c_menu.add_command(label="60-80", command=lambda: SectionQuery(self.tree_view).section(self.tree_view, 'c', 60, 80))
        c_menu.add_command(label="80-100", command=lambda: SectionQuery(self.tree_view).section(self.tree_view, 'c', 80, 100))
        total_menu.add_command(label="升序", command=lambda: TreeviewSortColumn().total_sort(self.tree_view))
        total_menu.add_command(label="降序", command=lambda: TreeviewSortColumn().total_sort(self.tree_view, "desc"))

        # 显示菜单
        root.config(menu=menubar)

        # 绑定单击离开事件
        self.tree_view.bind('', self.tree_view_click)

        # 捕获关闭按钮
        root.protocol("WM_DELETE_WINDOW", lambda: self.callback(root))

        # 事件循环
        root.mainloop()

    def tree_view_click(self, event):
        """点击表格中的一项数据后将其显示在相应文本框上"""
        for item in self.tree_view.selection():
            item_text = self.tree_view.item(item, "values")
            self.stu_id.set(item_text[0])
            self.stu_name.set(item_text[1])
            self.stu_python.set(item_text[2])
            self.stu_c.set(item_text[3])

    def callback(self, root):
        """退出时的询问"""
        if askokcancel("询问", "是否关闭该窗口?"):
            root.destroy()

添加学生信息模块代码

from database import Database
from tkinter.messagebox import *


class AddInfo(object):
    def __init__(self, stu_id, stu_name, stu_python, stu_c):
        """添加学生信息"""
        db = Database()
        stu_id = stu_id.get()
        stu_name = stu_name.get()
        try:
            if not(stu_id.strip() and stu_name.strip()):
                raise ValueError
            stu_python = int(stu_python.get())
            stu_c = int(stu_c.get())
            if 0 <= stu_python <= 100 and 0 <= stu_c <= 100:
                if db.prepare(f"select * from student where stu_id='{stu_id}'") == 0:
                    sql = f"insert into student values('{stu_id}', '{stu_name}', {stu_python}, {stu_c})"
                    db.prepare(sql)
                    db.update()
                    showinfo("提示", "添加成功")
                else:
                    showerror("添加失败", "该学号重复")
            else:
                showerror("添加失败", "各科分数应在0-100之间")
        except ValueError:
            showerror("添加失败", "信息未填写完整或者成绩输入为非数字")

查询学生信息模块代码

from database import Database
from tkinter.messagebox import *


class SearchInfo(object):
    def __init__(self, stu_id, stu_name, stu_python, stu_c, tree_view):
        """模糊查询"""
        db = Database()
        x = tree_view.get_children()
        for item in x:
            tree_view.delete(item)
        stu_name = stu_name.get()
        stu_id = stu_id.get()
        stu_python = stu_python.get()
        stu_c = stu_c.get()
        try:
            if stu_python != '':
                stu_python = int(stu_python)
            else:
                stu_python = 0
            if stu_c != '':
                stu_c = int(stu_c)
            else:
                stu_c = 0

            # 该sql语句筛选出你模糊查询的各种数据(可以组合)
            sql = f'''select * from student where (stu_id like '%{stu_id}%' or if(not stu_id, NULL, '') = '{stu_id}') 
                    and (stu_name like '%{stu_name}%' or if(not stu_name, '', NULL)='{stu_name}') and 
                    (if(not python, NULL, 0)={stu_python} or cast(python as char) like '%{stu_python}%') and 
                    (if(not c, NULL, 0)={stu_c} or cast(c as char) like '%{stu_c}%')'''
            # 只有文本框内有有效数据时才执行该语句
            if (stu_id or stu_name or stu_python or stu_c) and db.prepare(sql):
                db.update()
                showinfo("提示", "已完成查询")
                student_tuple = db.cursor.fetchall()
                for item in student_tuple:
                    tree_view.insert('', 'end', values=item)
            else:
                showerror("查询失败", "未查询到该学生信息")
        except ValueError:
            showerror("查询失败", "成绩只能为数字")
        db.close()

显示学生信息模块代码

from database import Database


class ShowInfo(object):
    def __init__(self, tree_view):
        """将所有学生信息显示在表格上"""
        db = Database()
        x = tree_view.get_children()
        for item in x:
            tree_view.delete(item)
        db.cursor.execute("select * from student")
        student_tuple = db.cursor.fetchall()
        for item in student_tuple:
            tree_view.insert("", 'end', values=item)

删除学生信息模块代码

from database import Database
from tkinter.messagebox import *


class DelInfo(object):
    def __init__(self, stu_id, stu_name, stu_python, stu_c):
        """模糊删除"""
        db = Database()
        stu_id = stu_id.get()
        stu_name = stu_name.get()
        stu_python = stu_python.get()
        stu_c = stu_c.get()
        try:
            if stu_python != '':
                stu_python = int(stu_python)
            else:
                stu_python = 0
            if stu_c != '':
                stu_c = int(stu_c)
            else:
                stu_c = 0
            sql = f'''select * from student where (stu_id like '%{stu_id}%' or if(not stu_id, NULL, '') = '{stu_id}') 
                    and (stu_name like '%{stu_name}%' or if(not stu_name, '', NULL)='{stu_name}') and
                    (if(not python, NULL, 0)={stu_python} or cast(python as char) like '%{stu_python}%') 
                    and (if(not c, NULL, 0)={stu_c} or cast(c as char) like '%{stu_c}%')'''
            if (stu_id or stu_name or stu_python or stu_c) and db.prepare(sql):
                db.update()
                stu_tuple = db.cursor.fetchall()
                for i in range(len(stu_tuple)):
                    if askokcancel("提示", f"是否删除该学生的信息(学号:{stu_tuple[i][0]} 姓名:{stu_tuple[i][1]} Python:{stu_tuple[i][2]} C语言:{stu_tuple[i][3]})"):
                        db.prepare(f"delete from student where (stu_id like '%{stu_id}%' or if(not stu_id, NULL, '') = '{stu_id}') and (stu_name like '%{stu_name}%' or if(not stu_name, '', NULL)='{stu_name}') and (if(not python, NULL, 0)={stu_python} or cast(python as char) like '%{stu_python}%') and (if(not c, NULL, 0)={stu_c} or cast(c as char) like '%{stu_c}%') limit 1")
                        db.update()
                        showinfo("提示", "删除成功")
            else:
                showerror("删除失败", "未查询到该学生信息")
        except ValueError:
            showerror("删除失败", "成绩只能为数字")

修改学生信息模块代码

from database import Database
from tkinter.messagebox import *


class ModifyInfo(object):
    def __init__(self, stu_id, stu_name, stu_python, stu_c):
        """修改学生信息"""
        db = Database()
        stu_id = stu_id.get()
        stu_name = stu_name.get()
        try:
            if not (stu_id.strip() and stu_name.strip()):
                raise ValueError
            stu_c = int(stu_c.get())
            stu_python = int(stu_python.get())
            if 0 <= stu_python <= 100 and 0 <= stu_c <= 100:
                if db.prepare(f"select * from student where stu_id={stu_id}") != 0:
                    db.prepare(f"update student set stu_name='{stu_name}', python={stu_python},"
                               f" c={stu_c} where stu_id='{stu_id}'")
                    db.update()
                    showinfo("提示", "修改成功")
                else:
                    showerror("修改失败", "未查询到该同学信息")
            else:
                showerror("修改失败", "各科分数应在0-100之间")
        except ValueError:
            showerror("修改失败", "信息未填写完整或者成绩输入为非数字")
        db.close()

分段筛选学生信息

from tkinter import *
from database import *
from tkinter.messagebox import *


class SectionQuery(object):
    def __init__(self, tree_view):
        """清空表格中显示的内容"""
        self.db = Database()
        x = tree_view.get_children()
        for item in x:
            tree_view.delete(item)

    def section(self, tree_view, *args):
        """快捷版分段显示"""
        self.db.prepare(f"select * from student where {args[0]}>{args[1]} and {args[0]}<{args[2]}")
        self.insert(tree_view)
        showinfo("提示", f"已筛选出{args[0]}成绩从{args[1]}—{args[2]}的学生的信息")


    def custom(self, tree_view):
        """自定义版分段显示"""
        # 创建自定义分段窗口
        top = Toplevel()
        # 使窗口位于屏幕中央
        screenwidth = top.winfo_screenwidth()
        screenheight = top.winfo_screenheight()
        width = 500
        high = 200
        top.geometry('%dx%d+%d+%d' % (width, high, (screenwidth - width) / 2, (screenheight - high) / 2))

        Label(top, text="Python").place(relx=0.48, rely=0, relwidth=0.1)
        Label(top, text="————").place(relx=0.48, rely=0.2, relwidth=0.1)
        Label(top, text="C语言").place(relx=0.48, rely=0.4, relwidth=0.1)
        Label(top, text="————").place(relx=0.48, rely=0.6, relwidth=0.1)

        python_limit1 = StringVar()
        python_limit2 = StringVar()
        c_limit1 = StringVar()
        c_limit2 = StringVar()

        Entry(top, textvariable=python_limit1).place(relx=0.1, rely=0.2, relwidth=0.35, height=25)
        Entry(top, textvariable=python_limit2).place(relx=0.6, rely=0.2, relwidth=0.35, height=25)
        Entry(top, textvariable=c_limit1).place(relx=0.1, rely=0.6, relwidth=0.35, height=25)
        Entry(top, textvariable=c_limit2).place(relx=0.6, rely=0.6, relwidth=0.35, height=25)

        mb = Menubutton(top, text="筛选", relief=RAISED)
        mb.place(relx=0.5, rely=0.8)

        filemenu = Menu(mb, tearoff=False)
        filemenu.add_command(label="按Python分段", command=lambda: self.section_python(python_limit1, python_limit2, tree_view))
        filemenu.add_command(label="按C语言分段", command=lambda: self.section_c(c_limit1, c_limit2, tree_view))
        filemenu.add_separator()
        filemenu.add_command(label="按Python和C语言分段", command=lambda: self.section_all(python_limit1, python_limit2, c_limit1, c_limit2, tree_view))
        mb.config(menu=filemenu)

    def check_data(self, limit1, limit2):
        """检查输入的数据是否合格"""
        try:
            limit1 = int(limit1.get())
            limit2 = int(limit2.get())

            if limit1 > limit2:
                up = limit1
                down = limit2
            else:
                up = limit2
                down = limit1

            return up, down
        except ValueError:
            showerror("分段筛选失败", "分段区间未填写完整或输入为非数字")

    def section_python(self, python_limit1, python_limit2, tree_view):
        """按python成绩分段筛选"""
        # 由与已有方法对异常进行了处理所以此处出现异常直接pass
        try:
            python_up, python_down = self.check_data(python_limit1, python_limit2)
            if self.db.prepare(f"select * from student where python>{python_down} and python<{python_up}") != 0:
                self.insert(tree_view)
                showinfo("提示", f"已筛选出Python成绩从{python_down}—{python_up}的学生的信息")
            else:
                showinfo("提示", f"没有Python成绩从{python_down}—{python_up}的学生的信息")
        except TypeError:
            pass
        self.db.close()

    def section_c(self, c_limit1, c_limit2, tree_view):
        """按照C语言成绩分段筛选"""
        try:
            c_up, c_down = self.check_data(c_limit1, c_limit2)
            if self.db.prepare(f"select * from student where c>{c_down} and c<{c_up}") != 0:
                self.insert(tree_view)
                showinfo("提示", f"已筛选出C语言成绩从{c_down}—{c_up}的学生的信息")
            else:
                showinfo("提示", f"没有C语言成绩从{c_down}—{c_up}的学生的信息")
        except TypeError:
            pass
        self.db.close()

    def section_all(self, python_limit1, python_limit2, c_limit1, c_limit2, tree_view):
        """按照python和C语言成绩分段筛选"""
        try:
            c_up, c_down = self.check_data(c_limit1, c_limit2)
            python_up, python_down = self.check_data(python_limit1, python_limit2)
            if self.db.prepare(f"select * from student where  c>{c_down} and c<{c_up} and python>{python_down} and python<{python_up}") != 0:
                self.insert(tree_view)
                showinfo("提示", f"已筛选出Python成绩从{python_down}—{python_up}"
                               f"C语言成绩从{c_down}—{c_up}的学生的信息")
            else:
                showinfo("提示", f"没有Python成绩从{python_down}—{python_up}"
                               f"C语言成绩从{c_down}—{c_up}的学生的信息")

        except TypeError:
            pass
        self.db.close()

    def insert(self, tree_view):
        """"向表格中插入筛选出来的数据"""
        student_tuple = self.db.cursor.fetchall()
        for item in student_tuple:
            tree_view.insert("", 'end', values=item)

排序模块代码

from tkinter.messagebox import *
from database import Database


class TreeviewSortColumn(object):  # Treeview、列名、排列方式
    def table_sort(self, tv, col, reverse):
        """点击表头进行排序"""
        # 因为排序utf-8编号问题所以汉字排序不是按首字母来的所以转化为gbk编码
        if col == 'stu_python' or col == 'stu_c':
            l = [(int(tv.set(k, col)), k) for k in tv.get_children('')]
        else:
            l = [(tv.set(k, col), k) for k in tv.get_children('')]
        if col == 'stu_name':
            l = [(i[0].encode('GBK'), i[1]) for i in l]
            l.sort(reverse=reverse)
            l = [(i[0].decode('GBK'), i[1])for i in l]
        else:
            l.sort(reverse=reverse)  # 排序方式
        # rearrange items in sorted positions
        for index, (val, k) in enumerate(l):  # 根据排序后索引移动
            tv.move(k, '', index)
        col_dict = {True: '降序', False: '升序', 'stu_id': '学号', 'stu_name': '姓名', 'stu_python': 'Python成绩', 'stu_c': 'C语言成绩'}
        showinfo("提示", f"已按{col_dict[col]}{col_dict[reverse]}排序")

        tv.heading(col, command=lambda: TreeviewSortColumn().table_sort(tv, col, not reverse))  # 重写标题,使之成为再点倒序的标题

    def total_sort(self, tree_view, select=''):
        """对总成绩排序"""
        db = Database()
        db.prepare("select * from student order by c+ python " + select)
        db.update()
        sort_dict = {'': '升序', 'desc': '降序'}
        showinfo("提示", f"已按总成绩{sort_dict[select]}排序")
        x = tree_view.get_children()
        for item in x:
            tree_view.delete(item)
        student_tuple = db.cursor.fetchall()
        db.close()
        for item in student_tuple:
            tree_view.insert("", 'end', values=item)

统计模块代码

from tkinter import ttk

import matplotlib.pyplot as plt
import matplotlib as mpl
import numpy as np
from tkinter import *
from tkinter.messagebox import *
from database import Database


class StatisticsInfo(object):
    def __init__(self):
        """创建显示统计的窗口"""
        top = Toplevel()
        self.db = Database()
        screenwidth = top.winfo_screenwidth()
        screenheight = top.winfo_screenheight()
        width = 700
        high = 600
        top.geometry('%dx%d+%d+%d' % (width, high, (screenwidth - width) / 2, (screenheight - high) / 2))

        # 创建显示数据的表格
        self.tree_view = ttk.Treeview(top, show='headings', column=('object', 'max', 'min', 'average', 'fail',
                                                                    'pass', 'middle', 'good', 'super', 'count'))
        self.tree_view.column('object', width=50, anchor="center")
        self.tree_view.column('max', width=50, anchor="center")
        self.tree_view.column('min', width=50, anchor="center")
        self.tree_view.column('average', width=50, anchor="center")
        self.tree_view.column('fail', width=50, anchor="center")
        self.tree_view.column('pass', width=50, anchor="center")
        self.tree_view.column('middle', width=50, anchor="center")
        self.tree_view.column('good', width=50, anchor="center")
        self.tree_view.column('super', width=50, anchor="center")
        self.tree_view.column('count', width=50, anchor="center")
        self.tree_view.heading('object', text='课程')
        self.tree_view.heading('max', text='最高分')
        self.tree_view.heading('min', text='最低分')
        self.tree_view.heading('average', text='平均分')
        self.tree_view.heading('fail', text='不及格')
        self.tree_view.heading('pass', text='及格')
        self.tree_view.heading('middle', text='中')
        self.tree_view.heading('good', text='良')
        self.tree_view.heading('super', text='优')
        self.tree_view.heading('count', text='总人数')

        self.tree_view.place(relx=0.02, rely=0.3, relwidth=0.96)
        self.statistics()

    def statistics(self):
        """"统计数据并显示在表格上"""
        if self.db.prepare(
                "select max(python), min(python), round(avg(python),1), count(python<60 or null), count(python<70 and "
                "python>60 or null), count(70
                "null), count(90) != 0:
            student_tuple = self.db.cursor.fetchall()
            student_tuple = ("Python",) + student_tuple[0]
            self.tree_view.insert("", 0, values=student_tuple)
            self.db.prepare("select max(c), min(c), round(avg(c),1), count(c<60 or null), count(c<70 and "
                            "c>60 or null), count(70
                            "null), count(90)
            student_tuple = self.db.cursor.fetchall()
            student_tuple = ("C语言",) + student_tuple[0]
            self.tree_view.insert("", 1, values=student_tuple)
            self.chart()
        else:
            showerror("统计失败", "没有学生数据无法进行统计")

    def chart(self):
        """"统计数据的柱状图"""
        # 柱状图
        # 使图形中的中文正常编码显示
        mpl.rcParams["font.sans-serif"] = ["SimHei"]
        # 每个柱子下标的索引
        self.db.prepare("select * from student")
        stu_tuple = self.db.cursor.fetchall()
        self.db.close()
        x = np.arange(len(stu_tuple))

        y = [x[2] for x in stu_tuple]
        y1 = [x[3] for x in stu_tuple]

        # 柱子的宽度
        bar_width = 0.35
        tick_label = [x[1] for x in stu_tuple]

        # 绘制柱状图并设置其各项属性
        plt.bar(x, y, bar_width, align="center", color="c", label="Python", alpha=0.5)
        plt.bar(x + bar_width, y1, bar_width, color="b", align="center", label="C语言", alpha=0.5)
        plt.tight_layout(pad=0.4, w_pad=10.0, h_pad=3.0)
        plt.title('学生成绩统计表')
        plt.xlabel("姓名")
        plt.ylabel("成绩")

        plt.xticks(x + bar_width / 2, tick_label)
        plt.xticks(rotation=-90)
        plt.yticks(np.arange(0, 101, 20))

        # 添加图例
        plt.legend(loc="upper left")

        plt.show()

启动模块代码

from login import Login

if __name__ == '__main__':
    Login()

你可能感兴趣的:(mysql,python,数据库)